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) { if (Expre.Count > 0) { bool foundBreak = false; for (int i = 0; i < Expre.Count; i++) { TypeReturn typeOfExp = Expre[i].CheckSemantics(scope_list, errors); //hago el chequeo semantico a la expresion de turno //si la expresion retorno por un break => el exp-sec no retorna valor if (typeOfExp is ReturnBreak) { foundBreak = true; //no retorno aqui para hacerle el chequeo semantico a cada expresion del exp-sec } if (i == Expre.Count - 1) { TypeExpSeq = foundBreak ? new ReturnBreak() : typeOfExp; //si se encontro un break retorno break para poderlo cogerlo en otro exp-sec, si no retorno el tipo de la ultima expresion return(TypeExpSeq); } } return(null); } else { TypeExpSeq = new ReturnNotValue(); //si no hay expresiones no se retorna valor return(TypeExpSeq); } }
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 Fun_Scope(string name, List <Tuple <string, TypeReturn> > param, TypeReturn retu, bool isSystem) { Param = param; Name = name; Retu = retu; IsSystem = isSystem; }
public override TypeReturn CheckSemantics(List <Scope> scope_list, List <Error> errors) { int cantCiclo = countOfClicles; countOfClicles = 0; scope_list.Add(new Scope()); for (int i = 0; i < Decl.Count; i++) { if (Decl[i] is FunDeclarationNode) //ver si es una declaración de funnción { i = CheckFuntion(i, scope_list, errors); //ver si es un bloque de funciones } else { if (Decl[i] is TypeDeclarationNode)//ver si es una declaración de tipo { i = CheckType(i, scope_list, errors); } else { Decl[i].CheckSemantics(scope_list, errors); //si es una declaración de variable } } } countOfClicles = cantCiclo; resulLet = expSec.CheckSemantics(scope_list, errors); //hago el checksemantics del exp-sec; scope_list.RemoveAt(scope_list.Count - 1); return(resulLet); }
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) { 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) { TypeReturn typeOfValue = Value.CheckSemantics(scope_list, errors); TypeReturn actual = typeOfValue; bool found; foreach (var access in Access_list) { found = false; if (access is AccessPto) //pregunto si es un acceso a un record { AccessPto aux = access as AccessPto; if (actual is ReturnRecord) { ReturnRecord temp = actual as ReturnRecord; typesList.Add(temp); //anado el record a mi lista de record //ver si el record tiene el campo .id foreach (var field in temp.Fields) { if (field.Item1.Equals(aux.Name)) //busco el campo igual al .id { actual = field.Item2; //guardo el tipo ese campo para la proxima iteracion found = true; break; } } if (!found) //si no encontro el campo { errors.Add(new Error(access.Line, access.Column, "El record no tiene ningun campo llamado " + aux.Name)); } } else //si el tipo al que se quiere hacer el . no es un record { errors.Add(new Error(access.Line, access.Column, "El tipo no es un record")); } } else { //es un acceso a un array AccessIndex aux = access as AccessIndex; if (actual is ReturnArray) { TypeReturn typeOfIndex = aux.Arg.CheckSemantics(scope_list, errors); //hago el chequeo semantico a [exp] if (!(typeOfIndex is ReturnInt)) //pregunto si es entera { errors.Add(new Error(access.Line, access.Column, "La expresion de indexer debe devolver un entero")); } ReturnArray temp = actual as ReturnArray; typesList.Add(temp); actual = temp.Type_Of_Elements; //el tipo del acceso es el mismo para todo los elementos del array } else { errors.Add(new Error(access.Line, access.Column, "El tipo que se desea indexar no es un array")); } } } return(actual); }
/// <summary> /// Chequea que la expresion de la condicion devuelva un entero /// </summary> /// <param name="scope_list">Lista de scope de la expresion de la condicion</param> /// <param name="errors">Lista de errores</param> protected void CheckCondition(List <Scope> scope_list, List <Error> errors) { TypeReturn typeOfCond = Cond.CheckSemantics(scope_list, errors); if (!(typeOfCond is ReturnInt)) //La expresion de la condicional del if tiene que devolver un entero { errors.Add(new Error(line, column, "La condicion del if debe retornar un entero")); } }
public override TypeReturn CheckSemantics(List <Scope> scope_list, List <Error> errors) { countOfClicles++; bool problem = false; //para no meter una variable que esta mal en el Scope //hay que ver que no exista una variable ni una funcion con el mismo nombre que la del for foreach (Scope scope in scope_list) { if (scope.Vars.Any(s => s.Key.Equals(this.Name))) //pregunto por las variables { errors.Add(new Error(line, column, "Ya existe una variable con el nombre: " + Name)); problem = true; //no puedo anadirla porque ya existe } else if (scope.Funcs.Any(s => s.Key.Equals(this.Name))) //pregunto por las funciones { errors.Add(new Error(line, column, "Ya existe una funcion con el nombre: " + Name)); problem = true; //no puedo anadirla porque ya existe } } TypeReturn typeOfAsign = Asig.CheckSemantics(scope_list, errors); if (!(typeOfAsign is ReturnInt)) { errors.Add(new Error(line, column, "La expresion de asignacion debe retonar un entero")); problem = true; //no puedo anadirla porque la variable no es un entero } TypeReturn typeOfTo = To.CheckSemantics(scope_list, errors); if (!(typeOfTo is ReturnInt)) { errors.Add(new Error(line, column, "La expresion del To debe retornar un entero")); } if (!problem) //si no preguntara esto podria estar anadiendo una variable con problemas al Scope (en el Scope no hay nada con errores!) { varFor = new Var_Scope(Name, typeOfAsign, true); Dictionary <string, Var_Scope> param = new Dictionary <string, Var_Scope>(); param.Add(Name, varFor); Scope scopeBodyFor = new Scope(param, new Dictionary <string, TypeReturn>(), new Dictionary <string, Fun_Scope>()); //el scope para la variable del for scope_list.Add(scopeBodyFor); //agrego la variable del for a la lista de scope para que el body del for pueda verla //if(Body!=null) TypeReturn typeOfBody = Body.CheckSemantics(scope_list, errors); if (!(typeOfBody is ReturnNotValue)) { errors.Add(new Error(line, column, "La expresion del body del for no debe devolver nada")); } scope_list.Remove(scopeBodyFor); //remuevo la variable del for } countOfClicles--; return(new ReturnNotValue()); }
public override TypeReturn CheckSemantics(List <Scope> scope_list, List <Error> errors) { TypeReturn t = Value.CheckSemantics(scope_list, errors); if (!(t is ReturnInt))//Mira a ver si el Value es entero { errors.Add(new Error(line, column, "La expresión debe ser entera")); } return(new ReturnInt()); }
public override bool CheckHeader(List <Scope> scope_list, List <Error> errors) { int cant = errors.Count();//ver los errores que hay hasta el momento if (Utils.IsStandardFunction(scope_list[0], Name)) { errors.Add(new Error(line, column, "Hay una funcion en la libreria estandar con el nombre '" + Name + "'")); } else if (scope_list[scope_list.Count - 1].Vars.ContainsKey(Name) || scope_list[scope_list.Count - 1].Funcs.ContainsKey(Name)) //ver si no hay una funcion o variable con ese nombre { errors.Add(new Error(line, column, "El nombre de la función '" + Name + "' ya esta en uso")); //añado el error } resul = Utils.FindType(scope_list, Retu); if (resul == null) //ver si el "tipo" existe { errors.Add(new Error(line, column, "El tipo de retorno de la función '" + Name + "' no existe")); //añado el error } Dictionary <string, string> e = new Dictionary <string, string>(); //para saber cuales son los parámetros y no repetir TypeReturn temp = null; foreach (var p in Param) { temp = Utils.FindType(scope_list, p.Item2); if (temp == null) //ver si el "tipo" existe { errors.Add(new Error(line, column, "El tipo del parámetro '" + p.Item1 + "' de la función no existe")); //añado el error } else { types.Add(new Tuple <string, Var_Scope>(p.Item1, new Var_Scope(p.Item1, temp))); } if (Param.Where(x => x.Item1 == p.Item1).Count() > 1 && !e.ContainsKey(p.Item1)) //hay mas de uno con el mismo nombre y si no lo he visto { errors.Add(new Error(line, column, "Existe más de un parámetro con el nombre '" + Name + "'")); //añado el error e.Add(p.Item1, p.Item1); //añado el nombre del parámetro al diccionario } } if (cant == errors.Count)//ver si no hubo error { f = new Fun_Scope(Name, types.Select(x => new Tuple <string, TypeReturn>(x.Item1, x.Item2.Var_type)).ToList(), resul); scope_list[scope_list.Count - 1].Funcs.Add(Name, f);//añadir la función al scope return(false); } return(true); }
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 }
public override TypeReturn CheckSemantics(List <Scope> scope_list, List <Error> errors) { TypeReturn t = Left.CheckSemantics(scope_list, errors); if (!(t is ReturnInt))//Mira si la parte izquierda no es Entera { errors.Add(new Error(line, column, "La expresión izquierda de la operación lógica debe ser entera")); } t = Right.CheckSemantics(scope_list, errors); if (!(t is ReturnInt))//Mira si la parte derecha no es Entera { errors.Add(new Error(line, column, "La expresión derecha de la operación lógica debe ser entera")); } return(new ReturnInt()); }
public override TypeReturn CheckSemantics(List <Scope> scope_list, List <Error> errors) { CheckCondition(scope_list, errors); //chequeo que la expresion de la condicion devuelva un entero TypeReturn typeOfBody = Body.CheckSemantics(scope_list, errors); if (!(typeOfBody is ReturnNotValue)) //La expresion del body no puede retornar ningun valor { errors.Add(new Error(line, column, "La expresion del cuerpo del if no puede devolver ningun valor")); } if (typeOfBody is ReturnBreak) //pregunto si el body del if es un break para saberlo por si estoy dentro de un exp-sec { return(new ReturnBreak()); } return(new ReturnNotValue()); //si no retorno ningun valor }
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) { countOfClicles++; TypeReturn typeOfCondi = Condi.CheckSemantics(scope_list, errors); if (!(typeOfCondi is ReturnInt)) //La expresion de la condicional del if tiene que devolver un entero { errors.Add(new Error(line, column, "La condicion del while debe retornar un entero")); } TypeReturn typeOfBody = Body.CheckSemantics(scope_list, errors); if (!(typeOfBody is ReturnNotValue)) { errors.Add(new Error(line, column, "La expresion del body del while no debe retornar ningun valor")); } countOfClicles--; return(new ReturnNotValue()); }
//---------------------chequea el bloque de tipos int CheckType(int first, List <Scope> scope_list, List <Error> errors) { int last = first; Dictionary <string, string> tem = new Dictionary <string, string>(); //guardo todos los nombres de los tipos List <TypeDeclarationNode> no_recursive_types = new List <TypeDeclarationNode>(); //guardo solo los alias y los arrays que no pueden caer en un ciclo Dictionary <string, TypeDeclarationNode> typ = new Dictionary <string, TypeDeclarationNode>(); //guardo los que no son alias for (int i = first; i < Decl.Count; i++) { last = i; if (Decl[i] is TypeDeclarationNode) { string name = ((TypeDeclarationNode)Decl[i]).Id;//cojo el nombre del type if (Utils.IsSystemType(name)) { errors.Add(new Error(Decl[i].line, Decl[i].column, "No se puede crear un tipo con el nombre de 'int' o de 'string'")); } else if (scope_list[scope_list.Count - 1].Types.ContainsKey(name) || tem.ContainsKey(name)) //ver si hay un tipo con ese nombre. { errors.Add(new Error(Decl[i].line, Decl[i].column, "Existe un tipo con el nombre " + "'" + name + "'")); } else { if (Decl[i] is AliasDecNode || Decl[i] is ArrayDecNode) { no_recursive_types.Add((TypeDeclarationNode)Decl[i]); //Añado el alias o array en su lista } else { typ.Add(name, (TypeDeclarationNode)Decl[i]); //Añado el TypeDeclarationNode en su diccionario } tem.Add(name, name); //añado el nombre de cada tipo } } else { last = i - 1; break; } } //--------chequeo los ciclos en los alias o arrays int cant = 0; while (cant != no_recursive_types.Count())//verificar que los alias esten correctos { cant = no_recursive_types.Count(); for (int i = 0; i < no_recursive_types.Count; i++) { if (no_recursive_types[i] is AliasDecNode) { var t = Utils.FindType(scope_list, ((AliasDecNode)no_recursive_types[i]).Value_redef);//me dice si el tipo existe y me lo dá if (t != null) { scope_list[scope_list.Count() - 1].Types.Add(no_recursive_types[i].Id, t); no_recursive_types.Remove(no_recursive_types[i]);//lo quito de la lista de alias i = i - 1; } else { if (typ.ContainsKey(((AliasDecNode)no_recursive_types[i]).Value_redef)) { typ.Add(no_recursive_types[i].Id, typ[((AliasDecNode)no_recursive_types[i]).Value_redef]); no_recursive_types.Remove(no_recursive_types[i]); i = i - 1; } } } else if (no_recursive_types[i] is ArrayDecNode) { var t = Utils.FindType(scope_list, ((ArrayDecNode)no_recursive_types[i]).Value);//me dice si el tipo existe y me lo dá if (t != null) { scope_list[scope_list.Count() - 1].Types.Add(no_recursive_types[i].Id, new ReturnArray(no_recursive_types[i].Id, t)); no_recursive_types.Remove(no_recursive_types[i]);//lo quito de la lista de alias i = i - 1; } else { if (typ.ContainsKey(((ArrayDecNode)no_recursive_types[i]).Value)) { typ.Add(no_recursive_types[i].Id, no_recursive_types[i]); no_recursive_types.Remove(no_recursive_types[i]); i = i - 1; } } } } } if (no_recursive_types.Count() > 0)//hay ciclo o error { for (int i = 0; i < no_recursive_types.Count(); i++) { if (no_recursive_types[i] is ArrayDecNode) { errors.Add(new Error(no_recursive_types[i].line, no_recursive_types[i].column, "El array '" + no_recursive_types[i].Id + "' es recursivo , es mutuamente recursivo o su tipo es invalido")); } else { errors.Add(new Error(no_recursive_types[i].line, no_recursive_types[i].column, "Error en el alias el tipo no pasa a traves de ningún record o array")); } } } //---ver si estan bien cant = 0; while (cant != typ.Count()) { cant = typ.Count(); foreach (var t in typ) { if (t.Key != t.Value.Id)//es un alias { var temp = (scope_list[scope_list.Count - 1].Types.ContainsKey(t.Value.Id)) ? scope_list[scope_list.Count - 1].Types[t.Value.Id] : null; if (temp != null)// era un alias al que ya resolvi su tipo { scope_list[scope_list.Count - 1].Types.Add(t.Key, temp); typ.Remove(t.Key);//lo quito de la lista del diccionario typ break; } else if (!typ.ContainsKey(t.Value.Id))//Es imposible resolver el alias pues el tipo al que hace referencia dio error al resolverse { errors.Add(new Error(t.Value.line, t.Value.column, "No se pudo resolver el alias '" + t.Key + "'")); typ.Remove(t.Key);//lo quito de la lista del diccionario typ break; } continue; } if (t.Value is ArrayDecNode)//si es una declaración de Array { var v = Utils.FindType(scope_list, ((ArrayDecNode)t.Value).Value); if (v != null) { scope_list[scope_list.Count() - 1].Types.Add(t.Key, new ReturnArray(t.Value.Id, v)); typ.Remove(t.Key);//lo quito de la lista del diccionario typ break; } else { if (!typ.ContainsKey(((ArrayDecNode)t.Value).Value)) { errors.Add(new Error(t.Value.line, t.Value.column, "No existe el tipo con el nombre " + "'" + ((ArrayDecNode)t.Value).Value + "'")); typ.Remove(t.Key);//lo quito de la lista de typ break; } } } if (t.Value is RecordDecNode)//si es una declaración de Record { int entro = 0; var params_record = new List <Tuple <string, TypeReturn> >(); //guardo los campos de los record foreach (var par in ((RecordDecNode)t.Value).Value) //recorro los campos de los record { var v = Utils.FindType(scope_list, par.Item2); //veo el tipo de cada record if (v != null) //si existe el tipo { params_record.Add(new Tuple <string, TypeReturn>(par.Item1, v)); //añado el campo con su tipo continue; } else { entro = 1; if (!typ.ContainsKey(par.Item2)) { errors.Add(new Error(t.Value.line, t.Value.column, "No existe el tipo con el nombre " + "'" + par.Item2 + "'")); typ.Remove(t.Key);//lo quito de la lista de typ entro = 2; break; } } } if (entro == 0)//No hay ningún conflicto con los tipos, todos estan en el scope { var aux = new ReturnRecord(t.Value.Id, params_record); scope_list[scope_list.Count() - 1].Types.Add(t.Key, aux); //Añado al Scope (t.Value as RecordDecNode).record = aux; //lo guardo para usarlo en la generacion de codigo typ.Remove(t.Key); //lo quito de la lista de alias break; } if (entro == 2) { break; //es porque modifique y estoy haciendo un foreach } } } } List <Tuple <string, string> > toRemove = new List <Tuple <string, string> >(); //borrar los alias que estan bien antes de llenar los tipo recursivos por ultima vez foreach (var t in typ) //recorro los que quedan en typ y lleno al diccionario "type_scope" { if (t.Key != t.Value.Id) //Es un alias { toRemove.Add(new Tuple <string, string>(t.Key, t.Value.Id)); continue; } if (t.Value is RecordDecNode) { ReturnRecord aux = new ReturnRecord(t.Value.Id, new List <Tuple <string, TypeReturn> >()); scope_list[scope_list.Count - 1].Types.Add(t.Key, aux); //la lista de los campos esta vacia (t.Value as RecordDecNode).record = aux; //lo guardo para usarlo en la generacion de codigo } if (t.Value is ArrayDecNode) { scope_list[scope_list.Count - 1].Types.Add(t.Key, new ReturnArray(t.Value.Id, null));//el tipo del array no se conoce } } while (toRemove.Count > 0)//quito los alias los meto en el scope con el type return del tipo a que hacen referencia. { var temp = toRemove[toRemove.Count - 1]; scope_list[scope_list.Count - 1].Types.Add(temp.Item1, scope_list[scope_list.Count - 1].Types[temp.Item2]); toRemove.Remove(temp); typ.Remove(temp.Item1); } foreach (var t in typ)//llenamos lo que esta en "type_scope" que no se conoce { if (t.Value is RecordDecNode) { foreach (var elem in ((RecordDecNode)t.Value).Value) //recorro para llenar los campos del record { TypeReturn x = Utils.FindType(scope_list, elem.Item2); //pido su tipo ((ReturnRecord)scope_list[scope_list.Count - 1].Types[t.Key]).Fields.Add(new Tuple <string, TypeReturn>(elem.Item1, x)); } } if (t.Value is ArrayDecNode) { ((ReturnArray)scope_list[scope_list.Count - 1].Types[t.Key]).Type_Of_Elements = scope_list[scope_list.Count - 1].Types[((ArrayDecNode)t.Value).Value];//lleno el tipo del array } } return(last); }
public Var_Scope(string name, TypeReturn type, bool noAsign) { Name = name; Var_type = type; NoAsign = noAsign; }
void FindTipoVariable(List <Scope> scope_list, string s) { TipoVariable = Utils.FindType(scope_list, s); }
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()); }
public Fun_Scope(string name, List <Tuple <string, TypeReturn> > param, TypeReturn retu) { Param = param; Name = name; Retu = retu; }
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 Var_Scope(string name, TypeReturn type) { Name = name; Var_type = type; NoAsign = false; }
} //contiene el tipo de retorno de los elementos del array public ReturnArray(string array_name, TypeReturn type_of_elements) { this.Array_name = array_name; this.Type_Of_Elements = type_of_elements; }