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); }
public override bool Equals(object obj) { ReturnRecord r = obj as ReturnRecord; if (r == null || r.Record_name != Record_name) { return(false); } return(true); }
//---------------------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 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 }