private void ProcessGlobals(MemberList globals)
{
// Locate the "Globals" struct so we can add fields to it.
Class globalsClass = (Class)Templates.GetMemberByName(appClass.Members,
"GlobalVars");
// Locate the "initialization" constructor so we can add initialization
// statements to it.
Debug.Assert(appClass.Members[1].Name.Name == ".ctor");
Method initCtor = (Method)appClass.Members[1];
// Locate the WriteString method so we can add statements to write out the globals
Method writer =
(Method)Templates.GetMemberByName(globalsClass.Members, "WriteString");
Method copier =
(Method)Templates.GetMemberByName(globalsClass.Members, "CopyContents");
Method traverser = (Method)Templates.GetMemberByName(globalsClass.Members, "TraverseFields");
Normalizer normalizer = new Normalizer(false);
Method getValue = (Method)Templates.GetMemberByName(globalsClass.Members, "GetValue");
Method setValue = (Method)Templates.GetMemberByName(globalsClass.Members, "SetValue");
System.Compiler.Switch switchGetValue =
(System.Compiler.Switch)Templates.GetStatementTemplate("GetFieldInfoSwitch");
getValue.Body.Statements.Add(switchGetValue);
System.Compiler.Switch switchSetValue =
(System.Compiler.Switch)Templates.GetStatementTemplate("SetFieldInfoSwitch");
setValue.Body.Statements.Add(switchSetValue);
for (int i = 0, n = globals.Count; i < n; i++)
{
// Make a shallow copy of the field since we're going to tinker with it
Field f = (Field)((Field)globals[i]).Clone();
string name = f.DeclaringType.Name.Name + "_" + f.Name.Name;
TypeNode zingType = f.Type;
if (GetTypeClassification(f.Type) == TypeClassification.Heap)
f.Type = this.ZingPtrType;
else if (!IsPredefinedType(f.Type))
f.Type = new TypeExpression(new QualifiedIdentifier(
new Identifier("Application"), zingType.Name), f.Type.SourceContext);
// Mangle the name to guarantee uniqueness across the globals
f.Name = new Identifier("priv_" + name);
f.Flags &= ~FieldFlags.Static;
// Sriram: I have made this into a public field so that
// the fieldInfo below works. If the field is internal
// then fieldInfo gets set to null (there is some access
// permission problem)
// Need to check with Tony as to
// whether this is tbe best solution
// The following two lines are Tony's code
//-----------------------------------------------------------
// f.Flags &= (FieldFlags)(~TypeFlags.VisibilityMask);
//f.Flags |= FieldFlags.Assembly;
//-----------------------------------------------------------
//This is my replacement
f.Flags |= FieldFlags.Public;
/*
Identifier idFieldName = new Identifier("id_" + name);
System.Compiler.Expression idTypeExpr =
new QualifiedIdentifier(
new QualifiedIdentifier(new Identifier("System"), new Identifier("Reflection")),
new Identifier("FieldInfo"));
System.Compiler.TypeNode idfType = new System.Compiler.TypeExpression(idTypeExpr);
Field idf = new Field(globalsClass, null, FieldFlags.Public|FieldFlags.Static,
idFieldName,
idfType, null);
idf.Initializer = Templates.GetExpressionTemplate("GetFieldInfo");
Replacer.Replace(idf.Initializer, "_class", globalsClass.Name);
Replacer.Replace(idf.Initializer, "_fieldName", new Literal(f.Name.Name, SystemTypes.String));
*/
Identifier idFieldName = new Identifier("id_" + name);
Field idf = new Field(globalsClass, null, FieldFlags.Public | FieldFlags.Static,
idFieldName,
SystemTypes.Int32, null);
idf.Initializer = new Literal(i, SystemTypes.Int32);
SwitchCase getCase = ((System.Compiler.Switch)Templates.GetStatementTemplate("GetFieldInfoCase")).Cases[0];
Replacer.Replace(getCase, "_fieldId", new Literal(i, SystemTypes.Int32));
Replacer.Replace(getCase, "_fieldName", new Identifier(f.Name.Name));
switchGetValue.Cases.Add(getCase);
SwitchCase setCase = ((System.Compiler.Switch)Templates.GetStatementTemplate("SetFieldInfoCase")).Cases[0];
Replacer.Replace(setCase, "_fieldId", new Literal(i, SystemTypes.Int32));
Replacer.Replace(setCase, "_fieldName", new Identifier(f.Name.Name));
TypeExpression tn = f.Type as TypeExpression;
Replacer.Replace(setCase, "_fieldType", tn != null ? tn.Expression : new Identifier(f.Type.Name.Name));
switchSetValue.Cases.Add(setCase);
//The last argument to the call below is a dont care
Property accessor = GetAccessorProperty("globalAccessor", f.Type,
new Identifier(name), f.Name, idFieldName, f.Name);
globalsClass.Members.Add(f);
globalsClass.Members.Add(idf);
globalsClass.Members.Add(accessor);
f.DeclaringType = globalsClass;
idf.DeclaringType = globalsClass;
accessor.DeclaringType = globalsClass;
if (accessor.Getter != null)
{
globalsClass.Members.Add(accessor.Getter);
accessor.Getter.DeclaringType = globalsClass;
}
if (accessor.Setter != null)
{
globalsClass.Members.Add(accessor.Setter);
accessor.Setter.DeclaringType = globalsClass;
}
if (zingType is Struct && !zingType.IsPrimitive && f.Type != SystemTypes.Decimal)
collectStructAccessors(true, (Struct)zingType, f.Name,
name, globalsClass);
if (f.Initializer != null)
{
Statement stmt = Templates.GetStatementTemplate("InitializeGlobal");
Replacer.Replace(stmt, "_FieldName", f.Name);
Replacer.Replace(stmt, "_FieldInitializer", normalizer.VisitFieldInitializer(f.Initializer));
initCtor.Body.Statements.Add(stmt);
f.Initializer = null;
}
writer.Body.Statements.Add(GetWriterStatement(null, zingType, f.Name));
copier.Body.Statements.Add(GetCopyStatement(f.Name));
traverser.Body.Statements.Add(GetTraverserStatement(null, zingType, f.Name));
/*if(GetTypeClassification(f.Type) == TypeClassification.Heap)
{
refTraverser.Body.Statements.Add(GetTraverserStatement(null, zingType, f.Name));
}
*/
}
}