using System.Reflection.Emit;
using System.Diagnostics;
-namespace CIR {
+namespace Mono.CSharp {
public class RootContext {
//
// Contains the parsed tree
//
- Tree tree;
+ static Tree tree;
//
// Contains loaded assemblies and our generated code as we go.
//
- public TypeManager TypeManager;
+ static public TypeManager TypeManager;
//
// The System.Reflection.Emit CodeGenerator
//
- CodeGen cg;
+ static CodeGen cg;
+ static public bool Optimize;
+
//
- // The module builder pointer
+ // The module builder pointer.
//
- ModuleBuilder mb;
+ static ModuleBuilder mb;
//
// Whether we are being linked against the standard libraries.
// This is only used to tell whether `System.Object' should
// have a parent or not.
//
- bool stdlib = true;
+ public static bool StdLib = true;
//
// This keeps track of the order in which classes were defined
// or abstract as well as the parent names (to implement new,
// override).
//
- ArrayList type_container_resolve_order;
- ArrayList interface_resolve_order;
+ static ArrayList type_container_resolve_order;
+ static ArrayList interface_resolve_order;
+
+ //
+ // Holds a reference to the Private Implementation Details
+ // class.
+ //
+ static TypeBuilder impl_details_class;
+
+ public static int WarningLevel = 2;
- public RootContext ()
+ //
+ // Constructor
+ //
+ static RootContext ()
{
- tree = new Tree (this);
+ tree = new Tree ();
TypeManager = new TypeManager ();
}
- public Tree Tree {
+ static public Tree Tree {
get {
return tree;
}
}
- public CodeGen CodeGen {
+ static public string MainClass;
+
+ static public CodeGen CodeGen {
get {
return cg;
}
}
}
- //
- // Returns the Type that represents the interface whose name
- // is `name'.
- //
-
- Type GetInterfaceTypeByName (string name)
+ public static void RegisterOrder (Interface iface)
{
- Interface parent;
- Type t = TypeManager.LookupType (name);
-
- if (t != null) {
-
- if (t.IsInterface)
- return t;
-
- string cause;
-
- if (t.IsValueType)
- cause = "is a struct";
- else if (t.IsClass)
- cause = "is a class";
- else
- cause = "Should not happen.";
-
- Report.Error (527, "`"+name+"' " + cause + ", need an interface instead");
-
- return null;
- }
-
- parent = (Interface) tree.Interfaces [name];
- if (parent == null){
- string cause = "is undefined";
-
- if (tree.Classes [name] != null)
- cause = "is a class";
- else if (tree.Structs [name] != null)
- cause = "is a struct";
-
- Report.Error (527, "`"+name+"' " + cause + ", need an interface instead");
- return null;
- }
-
- t = CreateInterface ((Interface) parent);
- if (t == null){
- Report.Error (529,
- "Inherited interface `"+name+"' is circular");
- return null;
- }
-
- return t;
+ interface_resolve_order.Add (iface);
}
- //
- // Returns the list of interfaces that this interface implements
- // Or null if it does not implement any interface.
- //
- // Sets the error boolean accoringly.
- //
- Type [] GetInterfaceBases (Interface iface, out bool error)
+ public static void RegisterOrder (TypeContainer tc)
{
- ArrayList bases = iface.Bases;
- Type [] tbases;
- int i;
-
- error = false;
- if (bases == null)
- return null;
-
- tbases = new Type [bases.Count];
- i = 0;
-
- foreach (string name in iface.Bases){
- Type t;
-
- t = GetInterfaceTypeByName (name);
- if (t == null){
- error = true;
- return null;
- }
-
- tbases [i++] = t;
- }
-
- return tbases;
+ type_container_resolve_order.Add (tc);
}
+ //
+ // The default compiler checked state
//
- // Creates the Interface @iface using the ModuleBuilder
+ static public bool Checked = false;
+
//
- // TODO:
- // Rework the way we recurse, because for recursive
- // definitions of interfaces (A:B and B:A) we report the
- // error twice, rather than once.
+ // Whether to allow Unsafe code
//
- TypeBuilder CreateInterface (Interface iface)
- {
- TypeBuilder tb = iface.TypeBuilder;
- Type [] ifaces;
- string name;
- bool error;
-
- if (tb != null)
- return tb;
-
- if (iface.InTransit)
- return null;
-
- iface.InTransit = true;
-
- name = iface.Name;
-
- ifaces = GetInterfaceBases (iface, out error);
-
- if (error)
- return null;
-
- tb = mb.DefineType (name,
- TypeAttributes.Interface |
- iface.InterfaceAttr |
- TypeAttributes.Abstract,
- null, // Parent Type
- ifaces);
- iface.TypeBuilder = tb;
-
- interface_resolve_order.Add (iface);
-
- TypeManager.AddUserType (name, tb);
-
- iface.InTransit = false;
- return tb;
- }
-
- string MakeFQN (string nsn, string name)
+ static public bool Unsafe = false;
+
+ static string MakeFQN (string nsn, string name)
{
string prefix = (nsn == "" ? "" : nsn + ".");
return prefix + name;
}
- Type LookupInterfaceOrClass (string ns, string name, bool is_class, out bool error)
- {
- TypeContainer parent;
- Type t;
-
- error = false;
- name = MakeFQN (ns, name);
-
- t = TypeManager.LookupType (name);
- if (t != null)
- return t;
-
- if (is_class){
- parent = (Class) tree.Classes [name];
- } else {
- parent = (Struct) tree.Structs [name];
- }
-
- if (parent != null){
- t = CreateType (parent, is_class);
- if (t == null){
- Report.Error (146, "Class definition is circular: `"+name+"'");
- error = true;
- return null;
- }
-
- return t;
- }
-
- return null;
- }
-
- //
- // returns the type for an interface or a class, this will recursively
- // try to define the types that it depends on.
- //
- Type GetInterfaceOrClass (TypeContainer tc, string name, bool is_class)
- {
- Type t;
- bool error;
-
- //
- // Attempt to lookup the class on our namespace
- //
- t = LookupInterfaceOrClass (tc.Namespace.Name, name, is_class, out error);
- if (error)
- return null;
-
- if (t != null)
- return t;
-
- //
- // Attempt to lookup the class on any of the `using'
- // namespaces
- //
-
- for (Namespace ns = tc.Namespace; ns != null; ns = ns.Parent){
- ArrayList using_list = ns.UsingTable;
-
- if (using_list == null)
- continue;
-
- foreach (string n in using_list){
- t = LookupInterfaceOrClass (n, name, is_class, out error);
- if (error)
- return null;
-
- if (t != null)
- return t;
- }
-
- }
- Report.Error (246, "Can not find type `"+name+"'");
- return null;
- }
-
- //
- // This function computes the Base class and also the
- // list of interfaces that the class or struct @c implements.
- //
- // The return value is an array (might be null) of
- // interfaces implemented (as Types).
- //
- // The @parent argument is set to the parent object or null
- // if this is `System.Object'.
- //
- Type [] GetClassBases (TypeContainer tc, bool is_class, out Type parent, out bool error)
- {
- ArrayList bases = tc.Bases;
- int count;
- int start, j, i;
-
- error = false;
-
- if (is_class)
- parent = null;
- else
- parent = TypeManager.value_type;
-
- if (bases == null){
- if (is_class){
- if (stdlib)
- parent = TypeManager.object_type;
- else if (tc.Name != "System.Object")
- parent = TypeManager.object_type;
- } else {
- //
- // If we are compiling our runtime,
- // and we are defining ValueType, then our
- // parent is `System.Object'.
- //
- if (!stdlib && tc. Name == "System.ValueType")
- parent = TypeManager.object_type;
- }
-
- return null;
- }
-
- //
- // Bases should be null if there are no bases at all
- //
- count = bases.Count;
- Debug.Assert (count > 0);
-
- if (is_class){
- string name = (string) bases [0];
- Type first = GetInterfaceOrClass (tc, name, is_class);
-
- if (first == null){
- error = true;
- return null;
- }
-
- if (first.IsClass){
- parent = first;
- start = 1;
- } else {
- parent = TypeManager.object_type;
- start = 0;
- }
- } else {
- start = 0;
- }
-
- Type [] ifaces = new Type [count-start];
-
- for (i = start, j = 0; i < count; i++, j++){
- string name = (string) bases [i];
- Type t = GetInterfaceOrClass (tc, name, is_class);
-
- if (t == null){
- error = true;
- return null;
- }
-
- if (is_class == false && !t.IsInterface){
- Report.Error (527, "In Struct `"+tc.Name+"', type `"+
- name+"' is not an interface");
- error = true;
- return null;
- }
-
- if (t.IsSealed) {
- string detail = "";
-
- if (t.IsValueType)
- detail = " (a class can not inherit from a struct)";
-
- Report.Error (509, "class `"+tc.Name+
- "': Cannot inherit from sealed class `"+
- bases [i]+"'"+detail);
- error = true;
- return null;
- }
-
- if (t.IsClass) {
- if (parent != null){
- Report.Error (527, "In Class `"+tc.Name+"', type `"+
- name+"' is not an interface");
- error = true;
- return null;
- }
- }
-
- ifaces [j] = t;
- }
-
- return ifaces;
- }
-
- // <remarks>
- // Creates the TypeBuilder for the TypeContainer @tc (a Class or a Struct)
- // </remarks>
- //
- TypeBuilder CreateType (TypeContainer tc, bool is_class)
- {
- TypeBuilder tb = tc.TypeBuilder;
- Type parent;
- Type [] ifaces;
- bool error;
- string name;
-
- if (tb != null)
- return tb;
-
- if (tc.InTransit)
- return null;
- tc.InTransit = true;
-
- name = tc.Name;
-
- ifaces = GetClassBases (tc, is_class, out parent, out error);
-
- if (error)
- return null;
-
- type_container_resolve_order.Add (tc);
-
- tb = mb.DefineType (name,
- tc.TypeAttr | TypeAttributes.Class,
- parent,
- ifaces);
- tc.TypeBuilder = tb;
-
- TypeManager.AddUserType (name, tb, tc);
- tc.InTransit = false;
-
- return tb;
- }
-
// <remarks>
// This function is used to resolve the hierarchy tree.
// It processes interfaces, structs and classes in that order.
// It creates the TypeBuilder's as it processes the user defined
// types.
// </remarks>
- public void ResolveTree ()
+ static public void ResolveTree ()
{
- Hashtable ifaces, classes, structs;
-
- type_container_resolve_order = new ArrayList ();
-
//
// Interfaces are processed first, as classes and
// structs might inherit from an object or implement
// a set of interfaces, we need to be able to tell
// them appart by just using the TypeManager.
//
- ifaces = tree.Interfaces;
+
+ TypeContainer root = Tree.Types;
+
+ ArrayList ifaces = root.Interfaces;
if (ifaces != null){
interface_resolve_order = new ArrayList ();
- foreach (DictionaryEntry de in ifaces)
- CreateInterface ((Interface) de.Value);
+ foreach (Interface i in ifaces)
+ i.DefineInterface (mb);
}
+
+ type_container_resolve_order = new ArrayList ();
+
+ foreach (TypeContainer tc in root.Types)
+ tc.DefineType (mb);
- //
- // Process structs and classes next. Our code assumes
- // this order (just for error reporting purposes).
- //
- structs = tree.Structs;
- if (structs != null){
- foreach (DictionaryEntry de in structs)
- CreateType ((Struct) de.Value, false);
- }
+ if (root.Delegates != null)
+ foreach (Delegate d in root.Delegates)
+ d.DefineDelegate (mb);
- classes = tree.Classes;
- if (classes != null){
- foreach (DictionaryEntry de in classes)
- CreateType ((Class) de.Value, true);
- }
+ if (root.Enums != null)
+ foreach (Enum e in root.Enums)
+ e.DefineEnum (mb);
+
}
// <summary>
// methods, fields, etc) we need to "Define" them before we
// can save the Assembly
// </remarks>
- public void CloseTypes ()
+ static public void CloseTypes ()
{
- foreach (TypeBuilder t in TypeManager.UserTypes){
- try {
- t.CreateType ();
- } catch (Exception e){
- Console.WriteLine ("Caught Exception while creating type for " + t);
- Console.WriteLine (e);
+ TypeContainer root = Tree.Types;
+
+ ArrayList ifaces = root.Interfaces;
+
+ if (root.Enums != null)
+ foreach (Enum en in root.Enums)
+ en.CloseType ();
+
+ if (interface_resolve_order != null){
+ foreach (Interface iface in interface_resolve_order)
+ iface.CloseType ();
+ }
+
+ //
+ // We do this in two passes, first we close the structs,
+ // then the classes, because it seems the code needs it this
+ // way. If this is really what is going on, we should probably
+ // make sure that we define the structs in order as well.
+ //
+ if (type_container_resolve_order != null){
+ foreach (TypeContainer tc in type_container_resolve_order){
+ if (tc is Struct && tc.Parent == tree.Types){
+ tc.CloseType ();
+ }
+ }
+
+ foreach (TypeContainer tc in type_container_resolve_order){
+ if (!(tc is Struct && tc.Parent == tree.Types))
+ tc.CloseType ();
}
}
- }
+
+ if (root.Delegates != null)
+ foreach (Delegate d in root.Delegates)
+ d.CloseDelegate ();
+
+ //
+ // If we have a <PrivateImplementationDetails> class, close it
+ //
+ if (impl_details_class != null){
+ impl_details_class.CreateType ();
+ }
+ }
+
//
// Public function used to locate types, this can only
// be used after the ResolveTree function has been invoked.
//
// Returns: Type or null if they type can not be found.
//
- public Type LookupType (TypeContainer tc, string name, bool silent)
+ static public Type LookupType (DeclSpace ds, string name, bool silent, Location loc)
{
Type t;
- t = TypeManager.LookupType (MakeFQN (tc.Namespace.Name, name));
+ //
+ // For the case the type we are looking for is nested within this one
+ // or any base class
+ //
+ DeclSpace containing_ds = ds;
+ while (containing_ds != null){
+ Type current_type = containing_ds.TypeBuilder;
+
+ while (current_type != null) {
+ t = TypeManager.LookupType (current_type.FullName + "+" + name);
+ if (t != null)
+ return t;
+ current_type = current_type.BaseType;
+ }
+
+ containing_ds = containing_ds.Parent;
+ }
+
+ t = TypeManager.LookupType (MakeFQN (ds.Namespace.Name, name));
if (t != null)
return t;
if (t != null)
return t;
- for (Namespace ns = tc.Namespace; ns != null; ns = ns.Parent){
+ for (Namespace ns = ds.Namespace; ns != null; ns = ns.Parent){
ArrayList using_list = ns.UsingTable;
if (using_list == null)
}
if (!silent)
- Report.Error (246, "Cannot find type `"+name+"'");
+ Report.Error (246, loc, "Cannot find type `"+name+"'");
return null;
}
- public Type LookupType (TypeContainer tc, string name)
+ // <summary>
+ // This is the silent version of LookupType, you can use this
+ // to `probe' for a type
+ // </summary>
+ static public Type LookupType (TypeContainer tc, string name, Location loc)
{
- return LookupType (tc, name, true);
+ return LookupType (tc, name, true, loc);
}
- public bool IsNamespace (string name)
+ static public bool IsNamespace (string name)
{
Namespace ns;
return false;
}
+ static void Report1530 (Location loc)
+ {
+ Report.Error (1530, loc, "Keyword new not allowed for namespace elements");
+ }
+
// <summary>
// Populates the structs and classes with fields and methods
// </summary>
//
// This is invoked after all interfaces, structs and classes
// have been defined through `ResolveTree'
- public void PopulateTypes ()
+ static public void PopulateTypes ()
{
- if (interface_resolve_order != null)
+ TypeContainer root = Tree.Types;
+
+ if (interface_resolve_order != null){
foreach (Interface iface in interface_resolve_order)
- iface.Populate ();
+ if ((iface.ModFlags & Modifiers.NEW) == 0)
+ iface.Define (root);
+ else
+ Report1530 (iface.Location);
+ }
- if (type_container_resolve_order != null)
- foreach (TypeContainer tc in type_container_resolve_order)
- tc.Populate ();
- }
- public void EmitCode ()
- {
- Hashtable classes, structs;
-
- if ((classes = tree.Classes) != null){
- foreach (DictionaryEntry de in classes){
- TypeContainer tc = (TypeContainer) de.Value;
+ if (type_container_resolve_order != null){
+ foreach (TypeContainer tc in type_container_resolve_order)
+ if ((tc.ModFlags & Modifiers.NEW) == 0)
+ tc.Define (root);
+ else
+ Report1530 (tc.Location);
+ }
- tc.Emit ();
- }
+ ArrayList delegates = root.Delegates;
+ if (delegates != null){
+ foreach (Delegate d in delegates)
+ if ((d.ModFlags & Modifiers.NEW) == 0)
+ d.Define (root);
+ else
+ Report1530 (d.Location);
}
- if ((structs = tree.Structs) != null){
- foreach (DictionaryEntry de in structs){
- TypeContainer tc = (TypeContainer) de.Value;
+ ArrayList enums = root.Enums;
+ if (enums != null){
+ foreach (Enum en in enums)
+ if ((en.ModFlags & Modifiers.NEW) == 0)
+ en.Define (root);
+ else
+ Report1530 (en.Location);
+ }
+ }
+ static public void EmitCode ()
+ {
+ if (type_container_resolve_order != null){
+ foreach (TypeContainer tc in type_container_resolve_order)
+ tc.EmitConstants ();
+
+ foreach (TypeContainer tc in type_container_resolve_order)
tc.Emit ();
- }
}
}
- // <summary>
- // Compiling against Standard Libraries property.
- // </summary>
- public bool StdLib {
+ static public ModuleBuilder ModuleBuilder {
get {
- return stdlib;
- }
-
- set {
- stdlib = value;
+ return mb;
}
}
// Public Field, used to track which method is the public entry
// point.
//
- public MethodInfo EntryPoint;
+ static public MethodInfo EntryPoint;
+
+ //
+ // These are used to generate unique names on the structs and fields.
+ //
+ static int field_count;
+
+ //
+ // Makes an initialized struct, returns the field builder that
+ // references the data. Thanks go to Sergey Chaban for researching
+ // how to do this. And coming up with a shorter mechanism than I
+ // was able to figure out.
+ //
+ // This works but makes an implicit public struct $ArrayType$SIZE and
+ // makes the fields point to it. We could get more control if we did
+ // use instead:
+ //
+ // 1. DefineNestedType on the impl_details_class with our struct.
+ //
+ // 2. Define the field on the impl_details_class
+ //
+ static public FieldBuilder MakeStaticData (byte [] data)
+ {
+ FieldBuilder fb;
+ int size = data.Length;
+
+ if (impl_details_class == null)
+ impl_details_class = mb.DefineType (
+ "<PrivateImplementationDetails>", TypeAttributes.NotPublic);
+
+ fb = impl_details_class.DefineInitializedData (
+ "$$field-" + (field_count++), data,
+ FieldAttributes.Static | FieldAttributes.Assembly);
+
+ return fb;
+ }
}
}
+