public override void GenerateCode(ModuleBuilder moduleBuilder, TypeBuilder program, ILGenerator generator) { if (FunctionInfo.IsStandard) { foreach (var Argument in this.Arguments) { Argument.GenerateCode(moduleBuilder, program, generator); } generator.Emit(OpCodes.Call, this.FunctionInfo.MethodBuilder); } else { //-------------------------------------------------- // Guarda Los Argumentos En El Stack Auxiliar. //-------------------------------------------------- for (int i = 0; i < this.Arguments.Count(); i++) { var Argument = this.Arguments.ElementAt(i); generator.Emit(OpCodes.Ldsfld, Argument.ExpressionType.VirtualStack2); Argument.GenerateCode(moduleBuilder, program, generator); generator.Emit(OpCodes.Callvirt, GenericStackHelper.GetMethod("Push", Argument.ExpressionType.UnderlyingSystemType) ); } //-------------------------------------------------- // Salva El Valor De Las Variables Locales (Stack1) //-------------------------------------------------- VariableInfo[] Locals = this.FunctionInfo.Scope.GetDescendingVariableInfos().ToArray(); for (int i = 0; i < Locals.Length; i++) { Locals[i].DeclareVariable(program); generator.Emit(OpCodes.Ldsfld, Locals[i].TypeNode.VirtualStack1); generator.Emit(OpCodes.Ldsfld, Locals[i].FieldBuilder); generator.Emit(OpCodes.Callvirt, GenericStackHelper.GetMethod("Push", Locals[i].TypeNode.UnderlyingSystemType) ); } //-------------------------------------------------- // Traer De Stack2 Los Argumentos Para El LLamado De La Función. //-------------------------------------------------- for (int i = this.Arguments.Count() - 1; i >= 0; i--) { var Argument = this.Arguments.ElementAt(i); generator.Emit(OpCodes.Ldsfld, Argument.ExpressionType.VirtualStack2); generator.Emit(OpCodes.Callvirt, GenericStackHelper.GetMethod("Pop", Argument.ExpressionType.UnderlyingSystemType) ); generator.Emit(OpCodes.Stsfld, this.FunctionInfo.Parameters[i].FieldBuilder); } //-------------------------------------------------- // [Stack Status] // 1. func( arg_1, arg_2, ..., arg_n ) [Si 'func' Retorna] // (...) //-------------------------------------------------- generator.Emit(OpCodes.Call, this.FunctionInfo.MethodBuilder); LocalBuilder Ret = null; if (this.FunctionInfo.ReturnType != PredefinedTypes.VoidType) { Ret = generator.DeclareLocal(this.FunctionInfo.ReturnType.UnderlyingSystemType); generator.Emit(OpCodes.Stloc, Ret.LocalIndex); } for (int i = Locals.Length - 1; i >= 0; i--) { generator.Emit(OpCodes.Ldsfld, Locals[i].TypeNode.VirtualStack1); generator.Emit(OpCodes.Callvirt, GenericStackHelper.GetMethod("Pop", Locals[i].TypeNode.UnderlyingSystemType) ); generator.Emit(OpCodes.Stsfld, Locals[i].FieldBuilder); } if (this.FunctionInfo.ReturnType != PredefinedTypes.VoidType) { generator.Emit(OpCodes.Ldloc, Ret.LocalIndex); } } }
public override void GenerateCode(ModuleBuilder moduleBuilder, TypeBuilder program, ILGenerator generator) { //-------------------------------------------------- // Generate Stack Fields For Builtin Types (int & string). //-------------------------------------------------- PredefinedTypes.IntType.VirtualStack1 = program.DefineField( string.Format("STACK_{0}", ++TigerNode.VariablesDeclared), typeof(Stack <>).MakeGenericType(new Type[] { typeof(int) }), FieldAttributes.Static ); PredefinedTypes.IntType.VirtualStack2 = program.DefineField( string.Format("STACK_{0}", ++TigerNode.VariablesDeclared), typeof(Stack <>).MakeGenericType(new Type[] { typeof(int) }), FieldAttributes.Static ); PredefinedTypes.StrType.VirtualStack1 = program.DefineField( string.Format("STACK_{0}", ++TigerNode.VariablesDeclared), typeof(Stack <>).MakeGenericType(new Type[] { typeof(string) }), FieldAttributes.Static ); PredefinedTypes.StrType.VirtualStack2 = program.DefineField( string.Format("STACK_{0}", ++TigerNode.VariablesDeclared), typeof(Stack <>).MakeGenericType(new Type[] { typeof(string) }), FieldAttributes.Static ); //-------------------------------------------------- // [Stack Status] // 1. expression [Si 'expression' Retorna] //-------------------------------------------------- this.Expression.GenerateCode(moduleBuilder, program, generator); //-------------------------------------------------- // [Stack Status] //-------------------------------------------------- if (this.Expression.ExpressionType != PredefinedTypes.VoidType) { generator.Emit(OpCodes.Pop); } //-------------------------------------------------- // Main Return. //-------------------------------------------------- generator.Emit(OpCodes.Ret); //-------------------------------------------------- // Define Ctor For Program //-------------------------------------------------- var ConstructorBuilder = program.DefineConstructor(MethodAttributes.SpecialName | MethodAttributes.Static | MethodAttributes.Private | MethodAttributes.HideBySig | MethodAttributes.RTSpecialName, CallingConventions.Standard, System.Type.EmptyTypes); var ConstructorGenerator = ConstructorBuilder.GetILGenerator(); /* Stack1 - int */ ConstructorGenerator.Emit(OpCodes.Newobj, GenericStackHelper.GetDefaultConstructor(typeof(int))); ConstructorGenerator.Emit(OpCodes.Stsfld, PredefinedTypes.IntType.VirtualStack1); /* Stack2 - int */ ConstructorGenerator.Emit(OpCodes.Newobj, GenericStackHelper.GetDefaultConstructor(typeof(int))); ConstructorGenerator.Emit(OpCodes.Stsfld, PredefinedTypes.IntType.VirtualStack2); /* Stack1 - string */ ConstructorGenerator.Emit(OpCodes.Newobj, GenericStackHelper.GetDefaultConstructor(typeof(string))); ConstructorGenerator.Emit(OpCodes.Stsfld, PredefinedTypes.StrType.VirtualStack1); /* Stack2 - string */ ConstructorGenerator.Emit(OpCodes.Newobj, GenericStackHelper.GetDefaultConstructor(typeof(string))); ConstructorGenerator.Emit(OpCodes.Stsfld, PredefinedTypes.StrType.VirtualStack2); /* Stack1 & Stack2 - other types */ foreach (var TI in Program.scope.GetDescendingTypeInfos()) { if (!(TI.TypeNode is AliasTypeNode || TI.TypeNode is BuiltinType)) { /* Stack1 - <> */ ConstructorGenerator.Emit(OpCodes.Newobj, GenericStackHelper.GetDefaultConstructor(TI.TypeNode.UnderlyingSystemType) ); ConstructorGenerator.Emit(OpCodes.Stsfld, TI.TypeNode.VirtualStack1); /* Stack2 - <> */ ConstructorGenerator.Emit(OpCodes.Newobj, GenericStackHelper.GetDefaultConstructor(TI.TypeNode.UnderlyingSystemType) ); ConstructorGenerator.Emit(OpCodes.Stsfld, TI.TypeNode.VirtualStack2); } } ConstructorGenerator.Emit(OpCodes.Ret); }