void CreateEntryPointIL(ILGenerator il, FieldInfo site, TypeBuilder startupClass){
LocalBuilder globalScope = il.DeclareLocal(Typeob.GlobalScope);
//Emit code to create an engine. We do this explicitly so that we can control fast mode.
if (this.doFast)
il.Emit(OpCodes.Ldc_I4_1);
else
il.Emit(OpCodes.Ldc_I4_0);
//Run through the list of references and emit code to create an array of strings representing them
//but do not emit duplicates.
SimpleHashtable uniqueReferences = new SimpleHashtable((uint)this.vsaItems.Count);
ArrayList references = new ArrayList();
foreach (Object item in this.vsaItems){
if (item is VsaReference){
string assemblyName = ((VsaReference)item).Assembly.GetName().FullName;
if (uniqueReferences[assemblyName] == null){
references.Add(assemblyName);
uniqueReferences[assemblyName] = item;
}
}
}
if (this.implicitAssemblies != null){
foreach (Object item in this.implicitAssemblies){
Assembly a = item as Assembly;
if (a != null){
String assemblyName = a.GetName().FullName;
if (uniqueReferences[assemblyName] == null){
references.Add(assemblyName);
uniqueReferences[assemblyName] = item;
}
}
}
}
ConstantWrapper.TranslateToILInt(il, references.Count);
il.Emit(OpCodes.Newarr, Typeob.String);
int num = 0;
foreach (string referenceName in references){
il.Emit(OpCodes.Dup);
ConstantWrapper.TranslateToILInt(il, num++);
il.Emit(OpCodes.Ldstr, referenceName);
il.Emit(OpCodes.Stelem_Ref);
}
if (startupClass != null){
il.Emit(OpCodes.Ldtoken, startupClass);
if (this.rootNamespace != null)
il.Emit(OpCodes.Ldstr, this.rootNamespace);
else
il.Emit(OpCodes.Ldnull);
MethodInfo createEngineAndGetGlobalScopeWithTypeAndRootNamespace = Typeob.VsaEngine.GetMethod("CreateEngineAndGetGlobalScopeWithTypeAndRootNamespace");
il.Emit(OpCodes.Call, createEngineAndGetGlobalScopeWithTypeAndRootNamespace);
}else{
MethodInfo createEngineAndGetGlobalScope = Typeob.VsaEngine.GetMethod("CreateEngineAndGetGlobalScope");
il.Emit(OpCodes.Call, createEngineAndGetGlobalScope);
}
il.Emit(OpCodes.Stloc, globalScope);
// get global object instances and event source instances (CreateStartupClass scenario only)
if (site != null) this.CreateHostCallbackIL(il, site);
bool setUserEntryPoint = this.genDebugInfo;
// for every generated class make an instance and call the main routine method
// When there are multiple VsaStaticCode items, all members of relevance are lifted to the
// first one. VsaStaticCode does not munge with the runtime scope chain, and instead
// relies on the code here to set things up before the global code is called.
bool codeToSetupGlobalScopeEmitted = false; // have we hit the first VsaStaticCode item
foreach (Object item in this.vsaItems){
Type compiledType = ((VsaItem)item).GetCompiledType();
if (null != compiledType){
ConstructorInfo globalScopeConstructor = compiledType.GetConstructor(new Type[]{Typeob.GlobalScope});
MethodInfo globalCode = compiledType.GetMethod("Global Code");
if (setUserEntryPoint){
//Set the Global Code method of the first code item to be the place where the debugger breaks for the first step into
this.CompilerGlobals.module.SetUserEntryPoint(globalCode);
setUserEntryPoint = false; //Do it once only
}
il.Emit(OpCodes.Ldloc, globalScope);
il.Emit(OpCodes.Newobj, globalScopeConstructor);
if (!codeToSetupGlobalScopeEmitted && item is VsaStaticCode) {
// This is the first VsaStaticCode item which holds all the relevant members.
// Push it onto the runtime scope stack.
LocalBuilder firstStaticScope = il.DeclareLocal(compiledType); // all members lifted to this object
il.Emit(OpCodes.Stloc, firstStaticScope);
// Call globalScope.engine.PushScriptObject(firstStaticScope)
il.Emit(OpCodes.Ldloc, globalScope);
il.Emit(OpCodes.Ldfld, CompilerGlobals.engineField);
il.Emit(OpCodes.Ldloc, firstStaticScope);
il.Emit(OpCodes.Call, CompilerGlobals.pushScriptObjectMethod);
// Restore stack for the next Call instruction.
il.Emit(OpCodes.Ldloc, firstStaticScope);
codeToSetupGlobalScopeEmitted = true;
}
il.Emit(OpCodes.Call, globalCode);
il.Emit(OpCodes.Pop);
}
}
if (codeToSetupGlobalScopeEmitted) {
// A VsaStaticCode item was encountered and code to setup the runtime
// stack was emitted. Restore the stack.
il.Emit(OpCodes.Ldloc, globalScope);
il.Emit(OpCodes.Ldfld, CompilerGlobals.engineField);
il.Emit(OpCodes.Call, CompilerGlobals.popScriptObjectMethod);
il.Emit(OpCodes.Pop);
}
// a method needs a return opcode
il.Emit(OpCodes.Ret);
}