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 }
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); }
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; }