import edu.arizona.cs.mbel.parse.*;
import edu.arizona.cs.mbel.signature.*;
import edu.arizona.cs.mbel.instructions.*;
import edu.arizona.cs.mbel.metadata.*;
import edu.arizona.cs.mbel.mbel.*;
import edu.arizona.cs.mbel.emit.*;
import java.io.*;

public class example2{
   public static void main(String args[]) throws Exception{
      /// Create the Module itself, and set its values ///
      Module module = new Module("hello.exe", new byte[16],
                                 PE_Header.PE_SUBSYSTEM_WINDOWS_CUI);
      AssemblyInfo info = new AssemblyInfo(AssemblyInfo.SHA1, 1, 0, 1, 1, 0,
                                           null, "HelloWorld", "");
      module.setAssemblyInfo(info);


      TypeDef HelloWorld = new TypeDef("HelloWorldSpace", "HelloWorld",
                                       TypeDef.NotPublic|TypeDef.BeforeFieldInit);
      HelloWorld.addMethod(Method.makeDefaultConstructor());
                                       
      module.addTypeDef(HelloWorld);

      /// Create the System.Console.WriteLine(string) MethodRef ///
      TypeRef System_Console = new AssemblyTypeRef(AssemblyRefInfo.MSCORLIB, "System", "Console");
      MethodSignature callsitesig = new MethodSignature(
                                       false, false, CallingConvention.DEFAULT,
                                       new ReturnTypeSignature(ReturnTypeSignature.ELEMENT_TYPE_VOID),
                                          new ParameterSignature[]{
                                             new ParameterSignature(TypeSignature.STRING, false)
                                          }
                                    );
      MethodRef WriteLine = new MethodRef("WriteLine", System_Console, callsitesig);

      /// Create the Main method, which prints "Hello World!" ///
      MethodSignature MainSig = new MethodSignature(
                                       false, false, CallingConvention.DEFAULT,
                                       new ReturnTypeSignature(ReturnTypeSignature.ELEMENT_TYPE_VOID),
                                       null
                                    );

      Method Main = new Method("Main", 0, (Method.Private|Method.HideBySig|Method.Static), MainSig);
      HelloWorld.addMethod(Main);

      MethodBody body = new MethodBody(true, 1, null);
      Main.setMethodBody(body);

      InstructionList ilist = body.getInstructionList();
      ilist.append(new LDSTR("Hello World!"));
      ilist.append(new CALL(WriteLine));
      ilist.append(new RET());

      module.setEntryPoint(new EntryPoint(Main));

      /// Emit the module to a file (hello.exe) ///
      FileOutputStream fout = new FileOutputStream("hello.exe");
      Emitter emitter = new Emitter(module);
      emitter.emitModule(fout);
      fout.close();
   }
}
