Ejemplo n.º 1
0
        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);
        }
Ejemplo n.º 2
0
        public override bool Equals(object obj)
        {
            ReturnRecord r = obj as ReturnRecord;

            if (r == null || r.Record_name != Record_name)
            {
                return(false);
            }

            return(true);
        }
Ejemplo n.º 3
0
        //---------------------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);
        }
Ejemplo n.º 4
0
        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
        }