internal MethodBase GetMethodBase(CompilerGlobals compilerGlobals){
if (this.mb != null)
return this.mb;
if (this.cb != null)
return this.cb;
JSFunctionAttributeEnum jsFunctionAttributes = 0;
int extras = 3;
if (this.isMethod){
if (this.isConstructor && ((ClassScope)this.enclosing_scope).outerClassField != null){
extras = 1;
jsFunctionAttributes |= JSFunctionAttributeEnum.IsInstanceNestedClassConstructor;
}else
extras = 0;
}else if (!this.hasArgumentsObject)
extras = 2;
int np = this.formal_parameters.Length+extras;
Type[] ptypes = new Type[np];
Type rtype = Convert.ToType(this.ReturnType(null));
if (extras > 0){
if (this.isConstructor)
ptypes[np-1] = ((ClassScope)this.enclosing_scope).outerClassField.FieldType;
else
ptypes[0] = Typeob.Object;
jsFunctionAttributes |= JSFunctionAttributeEnum.HasThisObject;
}
if (extras > 1){
ptypes[1] = Typeob.VsaEngine;
jsFunctionAttributes |= JSFunctionAttributeEnum.HasEngine;
}
if (extras > 2){
ptypes[2] = Typeob.Object;
jsFunctionAttributes |= JSFunctionAttributeEnum.HasArguments;
}
if (this.must_save_stack_locals)
jsFunctionAttributes |= JSFunctionAttributeEnum.HasStackFrame;
if (this.isExpandoMethod)
jsFunctionAttributes |= JSFunctionAttributeEnum.IsExpandoMethod;
if (this.isConstructor){
for (int i = 0; i < np-extras; i++)
ptypes[i] = this.parameter_declarations[i].ParameterType;
}else{
for (int i = extras; i < np; i++)
ptypes[i] = this.parameter_declarations[i-extras].ParameterType;
}
if (this.enclosing_scope is ClassScope)
if (this.isConstructor){
this.cb = ((ClassScope)(this.enclosing_scope)).GetTypeBuilder().DefineConstructor(this.attributes&MethodAttributes.MemberAccessMask,
CallingConventions.Standard, ptypes);
}else{
String name = this.name;
if (this.implementedIfaceMethod != null){
JSMethod jsm = this.implementedIfaceMethod as JSMethod;
if (jsm != null) this.implementedIfaceMethod = jsm.GetMethodInfo(compilerGlobals);
name = this.implementedIfaceMethod.DeclaringType.FullName + "." + name;
}
TypeBuilder tb = ((ClassScope)(this.enclosing_scope)).GetTypeBuilder();
if (this.mb != null) return this.mb; //Might have been defined as a result of the above call
this.mb = tb.DefineMethod(name, this.attributes, rtype, ptypes);
if (this.implementedIfaceMethod != null)
((ClassScope)(this.enclosing_scope)).GetTypeBuilder().DefineMethodOverride(this.mb, this.implementedIfaceMethod);
}
else{
if (enclosing_scope is FunctionScope){ //dealing with a nested function/function expression. Mangle the name.
if (((FunctionScope)enclosing_scope).owner != null){
this.name = ((FunctionScope)enclosing_scope).owner.name+ "." + this.name;
jsFunctionAttributes |= JSFunctionAttributeEnum.IsNested;
}else{ //dealing with the dummy outer scope of a function expression
ScriptObject escope = enclosing_scope;
while (escope != null){
if (escope is FunctionScope && ((FunctionScope)escope).owner != null){
this.name = ((FunctionScope)escope).owner.name+ "." + this.name;
jsFunctionAttributes |= JSFunctionAttributeEnum.IsNested;
break;
}
escope = escope.GetParent();
}
}
}
//The name could still be a duplicate, so check against a table of names already used.
if (compilerGlobals.usedNames[this.name] != null)
this.name = this.name + ":" + (compilerGlobals.usedNames.count).ToString(CultureInfo.InvariantCulture);
compilerGlobals.usedNames[this.name] = this;
// Use the class writer associated with the global scope if the function is a global
// function or a nested function inside a global function. In these cases,
// compilerGlobals.classwriter will be setup incorrectly if the function is called
// from a code inside a class before it is declared.
ScriptObject classScope = this.enclosing_scope;
while (classScope != null && !(classScope is ClassScope))
classScope = classScope.GetParent();
this.classwriter = (classScope == null ? compilerGlobals.globalScopeClassWriter : compilerGlobals.classwriter);
this.mb = this.classwriter.DefineMethod(this.name, this.attributes, rtype, ptypes);
}
// the method is defined, we can now put debug info about the parameters
if (extras > 0){
if (this.mb != null)
this.mb.DefineParameter(1, (ParameterAttributes)0, "this");
else{
ParameterBuilder pb = this.cb.DefineParameter(np, (ParameterAttributes)0, "this");
pb.SetConstant(null);
extras = 0;
np--;
}
}
if (extras > 1)
this.mb.DefineParameter(2, (ParameterAttributes)0, "vsa Engine");
if (extras > 2)
this.mb.DefineParameter(3, (ParameterAttributes)0, "arguments");
for (int i = extras; i < np; i++){
ParameterBuilder pb = this.mb != null ?
this.mb.DefineParameter(i + 1, (ParameterAttributes)0, this.parameter_declarations[i-extras].identifier) :
this.cb.DefineParameter(i + 1, (ParameterAttributes)0, this.parameter_declarations[i-extras].identifier);
CustomAttributeList paramCustAttList = this.parameter_declarations[i-extras].customAttributes;
if (paramCustAttList != null){
CustomAttributeBuilder[] paramCustomAttributes = paramCustAttList.GetCustomAttributeBuilders(false);
for (int attIndex = 0; attIndex < paramCustomAttributes.Length; attIndex++)
pb.SetCustomAttribute(paramCustomAttributes[attIndex]);
}
}
if (jsFunctionAttributes > 0){
CustomAttributeBuilder cab = new CustomAttributeBuilder(CompilerGlobals.jsFunctionAttributeConstructor, new Object[1] {jsFunctionAttributes});
if (this.mb != null)
this.mb.SetCustomAttribute(cab);
else
this.cb.SetCustomAttribute(cab);
}
// deal with custom attributes
if (this.customAttributes != null){
CustomAttributeBuilder[] custAtt = this.customAttributes.GetCustomAttributeBuilders(false);
for (int j = 0; j < custAtt.Length; j++){
if (this.mb != null)
this.mb.SetCustomAttribute(custAtt[j]);
else
this.cb.SetCustomAttribute(custAtt[j]);
}
}
if (this.clsCompliance == CLSComplianceSpec.CLSCompliant)
if (this.mb != null)
this.mb.SetCustomAttribute(new CustomAttributeBuilder(CompilerGlobals.clsCompliantAttributeCtor, new Object[]{true}));
else
this.cb.SetCustomAttribute(new CustomAttributeBuilder(CompilerGlobals.clsCompliantAttributeCtor, new Object[]{true}));
else if (this.clsCompliance == CLSComplianceSpec.NonCLSCompliant)
if (this.mb != null)
this.mb.SetCustomAttribute(new CustomAttributeBuilder(CompilerGlobals.clsCompliantAttributeCtor, new Object[]{false}));
else
this.cb.SetCustomAttribute(new CustomAttributeBuilder(CompilerGlobals.clsCompliantAttributeCtor, new Object[]{false}));
if (this.mb != null){
this.mb.InitLocals = true;
return this.mb;
}else{
this.cb.InitLocals = true;
return this.cb;
}
}