diff options
Diffstat (limited to 'mcs/ilasm/codegen/ClassTable.cs')
-rw-r--r-- | mcs/ilasm/codegen/ClassTable.cs | 250 |
1 files changed, 250 insertions, 0 deletions
diff --git a/mcs/ilasm/codegen/ClassTable.cs b/mcs/ilasm/codegen/ClassTable.cs new file mode 100644 index 00000000000..0c2b5adcaca --- /dev/null +++ b/mcs/ilasm/codegen/ClassTable.cs @@ -0,0 +1,250 @@ +// +// Mono.ILASM.ClassTable.cs +// +// Author(s): +// Jackson Harper (Jackson@LatitudeGeo.com) +// +// (C) 2003 Jackson Harper, All rights reserved +// + +using PEAPI; +using System; +using System.Collections; + +namespace Mono.ILASM { + + public class ClassTable { + + private class ClassTableItem { + + private static readonly int DefinedFlag = 2; + + private int flags; + + public ArrayList LocationList; + public ClassDef Class; + public MethodTable method_table; + public FieldTable field_table; + + public ClassTableItem (ClassDef klass, Location location) + { + flags = 0; + Class = klass; + LocationList = new ArrayList (); + LocationList.Add (location); + method_table = new MethodTable (klass); + field_table = new FieldTable (klass); + } + + public bool Defined { + get { return ((flags & DefinedFlag) != 0); } + set { + if (value) + flags |= DefinedFlag; + else + flags ^= DefinedFlag; + } + } + + public bool CheckDefined () + { + if (!Defined) + return false; + + if (!FieldTable.CheckDefined ()) + return false; + + if (!MethodTable.CheckDefined ()) + return false; + + return true; + } + + public MethodTable MethodTable { + get { return method_table; } + } + + public FieldTable FieldTable { + get { return field_table; } + } + + } + + protected readonly TypeAttr DefaultAttr; + protected Hashtable table; + protected PEFile pefile; + + public ClassTable (PEFile pefile) + { + DefaultAttr = TypeAttr.Public; + this.pefile = pefile; + table = new Hashtable (); + } + + public Class Get (string full_name) + { + ClassTableItem item = table[full_name] as ClassTableItem; + + if (item == null) + return null; + + return item.Class; + } + + public Class GetReference (string full_name, Location location) + { + ClassTableItem item = table[full_name] as ClassTableItem; + + if (item != null) { + item.LocationList.Add (location); + return item.Class; + } + + string name_space, name; + GetNameAndNamespace (full_name, out name_space, out name); + ClassDef klass = pefile.AddClass (DefaultAttr, name_space, name); + AddReference (full_name, klass, location); + + return klass; + } + + public MethodTable GetMethodTable (string full_name, Location location) + { + ClassTableItem item = table[full_name] as ClassTableItem; + + if (item == null) { + GetReference (full_name, location); + return GetMethodTable (full_name, location); + } + + return item.MethodTable; + } + + public FieldTable GetFieldTable (string full_name, Location location) + { + ClassTableItem item = table[full_name] as ClassTableItem; + + if (item == null) { + GetReference (full_name, location); + return GetFieldTable (full_name, location); + } + + return item.FieldTable; + } + + public ClassDef AddDefinition (string name_space, string name, + TypeAttr attr, Location location) + { + string full_name; + + if (name_space != null) + full_name = String.Format ("{0}.{1}", name_space, name); + else + full_name = name; + + ClassTableItem item = (ClassTableItem) table[full_name]; + + if (item == null) { + ClassDef klass = pefile.AddClass (attr, name_space, name); + AddDefined (full_name, klass, location); + return klass; + } + + item.Class.AddAttribute (attr); + item.Defined = true; + + return item.Class; + } + + public ClassDef AddDefinition (string name_space, string name, + TypeAttr attr, Class parent, Location location) + { + string full_name; + + if (name_space != null) + full_name = String.Format ("{0}.{1}", name_space, name); + else + full_name = name; + + ClassTableItem item = (ClassTableItem) table[full_name]; + + if (item == null) { + ClassDef klass = pefile.AddClass (attr, name_space, name, parent); + AddDefined (full_name, klass, location); + return klass; + } + + /// TODO: Need to set parent, will need to modify PEAPI for this. + item.Class.AddAttribute (attr); + item.Defined = true; + + return item.Class; + } + + /// <summary> + /// When there is no code left to compile, check to make sure referenced types where defined + /// TODO: Proper error reporting + /// </summary> + public void CheckForUndefined () + { + foreach (DictionaryEntry dic_entry in table) { + ClassTableItem table_item = (ClassTableItem) dic_entry.Value; + if (table_item.CheckDefined ()) + continue; + Report.Error (String.Format ("Type: {0} is not defined.", dic_entry.Key)); + } + } + + /// <summary> + /// If a type is allready defined throw an Error + /// </summary> + protected void CheckExists (string full_name) + { + ClassTableItem item = table[full_name] as ClassTableItem; + + if ((item != null) && (item.Defined)) { + Report.Error (String.Format ("Class: {0} defined in multiple locations.", + full_name)); + } + } + + protected void AddDefined (string full_name, ClassDef klass, Location location) + { + if (table.Contains (full_name)) + return; + + ClassTableItem item = new ClassTableItem (klass, location); + item.Defined = true; + + table[full_name] = item; + } + + protected void AddReference (string full_name, ClassDef klass, Location location) + { + if (table.Contains (full_name)) + return; + + ClassTableItem item = new ClassTableItem (klass, location); + + table[full_name] = item; + } + + public static void GetNameAndNamespace (string full_name, + out string name_space, out string name) { + + int last_dot = full_name.LastIndexOf ('.'); + + if (last_dot < 0) { + name_space = String.Empty; + name = full_name; + return; + } + + name_space = full_name.Substring (0, last_dot); + name = full_name.Substring (last_dot + 1); + } + + } + +} + |