예제 #1
0
 public override Type GenCode(ILGenerator ilGenerator, TypeBuilder parent, FieldBuilder IsBreakFields, List <FieldBuilder> level, Label endLabel)
 {
     if (Expre.Count > 0)
     {
         Type expType;
         for (int i = 0; i < Expre.Count - 1; i++) //por cada expresion genera codigo
         {
             //si alguna intermendia devuelve valor sacarla de la pila
             //dejar solo en la pila la ultima expresion
             expType = Expre[i].GenCode(ilGenerator, parent, IsBreakFields, level, endLabel);
             if (expType != null && expType != typeof(void))
             {
                 LocalBuilder local = ilGenerator.DeclareLocal(expType);
                 //saco de la pila lo que esta en el tope
                 ilGenerator.Emit(OpCodes.Stloc, local);
             }
             ////FALTA VER SI DEVUELVE BREAK ALGUNA EXPRESION
             if (TypeExpSeq is ReturnBreak)
             {
                 ilGenerator.Emit(OpCodes.Ldarg_0);
                 ilGenerator.Emit(OpCodes.Ldfld, IsBreakFields);
                 ilGenerator.Emit(OpCodes.Ldc_I4_1);
                 ilGenerator.Emit(OpCodes.Beq, endLabel);
             }
         }
         //el ultimo no lo saco de la pila
         expType = Expre[Expre.Count - 1].GenCode(ilGenerator, parent, IsBreakFields, level, endLabel); //genero el codigo de la ultima expresion
         if (TypeExpSeq is ReturnBreak)
         {
             if (expType != null && expType != typeof(void))
             {
                 LocalBuilder local = ilGenerator.DeclareLocal(expType);
                 //saco de la pila lo que esta en el tope
                 ilGenerator.Emit(OpCodes.Stloc, local);
             }
         }
         return(TypeExpSeq.MyType());
     }
     return(null); //no hay ninguna expresion en el exp-sec
 }
예제 #2
0
        public override Type GenCode(ILGenerator ilGenerator, TypeBuilder parent, FieldBuilder IsBreakFields, List <FieldBuilder> level, Label endLabel)
        {
            //Defino el tipo let como una clase anidada
            TypeBuilder let = parent.DefineNestedType("Let" + Utils.AutoNumeric, TypeAttributes.NestedPublic | TypeAttributes.Class);

            foreach (var dec in Decl)
            {
                if (dec is RecordDecNode)
                {
                    (dec as RecordDecNode).CreateType();
                }
                if (dec is FunDeclarationNode)
                {
                    (dec as FunDeclarationNode).CreateType(let);
                }
            }

            //Guardo las variables
            List <VarDeclarationNode> varib = new List <VarDeclarationNode>();

            //esto es para la declarando el campo que tendrá la referencia al padre al padre
            FieldBuilder fieldPare = let.DefineField("parent", parent, FieldAttributes.Public);

            level.Add(fieldPare);

            foreach (var dec in Decl)
            {
                if (dec is VarDeclarationNode)
                {
                    varib.Add((dec as VarDeclarationNode));
                }

                //Genero codigo de los record
                if (dec is RecordDecNode)
                {
                    (dec as RecordDecNode).GenCode();
                }
            }

            //Creo el constructor
            ConstructorBuilder letCrt = let.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new List <Type>()
            {
                parent
            }.ToArray());
            ILGenerator ilCrt = letCrt.GetILGenerator();

            //esto es para la referencia al padre
            ilCrt.Emit(OpCodes.Ldarg_0); //meto el this
            ilCrt.Emit(OpCodes.Ldarg_1); //meto el padre en la pila
            ilCrt.Emit(OpCodes.Stfld, fieldPare);


            //Crear las variables dentro de la clase let y asignarle el valor
            for (int i = 0; i < varib.Count; i++)
            {
                varib[i].GenCode(ilCrt, let, IsBreakFields, level, endLabel);
            }

            FieldBuilder field = let.DefineField("Break", typeof(bool), FieldAttributes.Public);

            ilCrt.Emit(OpCodes.Ldarg_0);  //meto el this
            ilCrt.Emit(OpCodes.Ldc_I4_0); //meto un cero en la pila
            ilCrt.Emit(OpCodes.Stfld, field);

            //Cerrar el constructor
            ilCrt.Emit(OpCodes.Ret);

            foreach (var dec in Decl)
            {
                //Genero codigo de la funcion
                if (dec is FunDeclarationNode)
                {
                    (dec as FunDeclarationNode).GenCode(null, let, default(FieldBuilder), level, default(Label));
                }
            }

            //Creo el metodo en el que se encuentra el body
            Type          res   = (resulLet is ReturnNil) ? typeof(object) : resulLet.MyType();
            MethodBuilder mLet  = let.DefineMethod("BodyLet", MethodAttributes.Public, CallingConventions.HasThis, res, new Type[] { });
            ILGenerator   ilMet = mLet.GetILGenerator();

            Label endLet = ilMet.DefineLabel();

            expSec.GenCode(ilMet, let, field, level, endLet);

            ilMet.MarkLabel(endLet);

            ilMet.Emit(OpCodes.Ldarg_0);
            ilMet.Emit(OpCodes.Ldfld, fieldPare);

            //meto en la pila el valor del break
            ilMet.Emit(OpCodes.Ldarg_0);
            ilMet.Emit(OpCodes.Ldfld, field);
            ilMet.Emit(OpCodes.Stfld, IsBreakFields);

            ilMet.Emit(OpCodes.Ret);

            // Crear el tipo que representa al Let.
            let.CreateType();

            level.RemoveAt(level.Count - 1);

            // Crear una instancia del tipo que representa al Let.
            ilGenerator.Emit(OpCodes.Ldarg_0);
            ilGenerator.Emit(OpCodes.Newobj, letCrt);

            // Llamar al método que representa el cuerpo del Let.
            ilGenerator.Emit(OpCodes.Callvirt, mLet);

            return((resulLet is ReturnNotValue) ? null : res);
        }
예제 #3
0
        public override void CreateType(TypeBuilder parent)
        {
            //Parametros ,empezando por el padre
            List <Type> param = new List <Type>()
            {
                parent
            };

            param.AddRange(types.Select(a => a.Item2.Var_type.MyType()));

            typeClass = parent.DefineNestedType(Name + Utils.AutoNumeric, TypeAttributes.NestedPublic | TypeAttributes.Class);

            ConstructorBuilder constructor = typeClass.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, param.ToArray());

            f.constr = constructor;

            MethodBuilder mFunc = typeClass.DefineMethod(Name, MethodAttributes.Public, CallingConventions.HasThis, resul.MyType(), new Type[] { });

            f.meth = mFunc;
        }