/// <summary>
/// Keeps track of the namespaces defined in the C# code.
+ ///
+ /// This is an Expression to allow it to be referenced in the
+ /// compiler parse/intermediate tree during name resolution.
/// </summary>
- public class Namespace {
+ public class Namespace : FullNamedExpression, IAlias {
static ArrayList all_namespaces = new ArrayList ();
static Hashtable namespaces_map = new Hashtable ();
/// </summary>
public Namespace (Namespace parent, string name)
{
+ // Expression members.
+ this.eclass = ExprClass.Namespace;
+ this.Type = null;
+ this.loc = Location.Null;
+
this.parent = parent;
string pname = parent != null ? parent.Name : "";
namespaces_map [fullname] = true;
}
+ public override Expression DoResolve (EmitContext ec)
+ {
+ return this;
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ throw new InternalErrorException ("Expression tree referenced namespace " + fullname + " during Emit ()");
+ }
+
public static bool IsNamespace (string name)
{
return namespaces_map [name] != null;
return Root.GetNamespace (name, create);
}
- public object Lookup (DeclSpace ds, string name)
+ public FullNamedExpression Lookup (DeclSpace ds, string name, Location loc)
{
- object o = Lookup (name);
+ IAlias o = (IAlias) defined_names [name];
Type t;
DeclSpace tdecl = o as DeclSpace;
t = tdecl.DefineType ();
if ((ds == null) || ds.CheckAccessLevel (t))
- return t;
+ return new TypeExpression (t, Location.Null);
}
Namespace ns = GetNamespace (name, false);
if ((t == null) || ((ds != null) && !ds.CheckAccessLevel (t)))
return null;
- return t;
+ return new TypeExpression (t, Location.Null);
}
public void AddNamespaceEntry (NamespaceEntry entry)
entries.Add (entry);
}
- public void DefineName (string name, object o)
+ public void DefineName (string name, IAlias o)
{
defined_names.Add (name, o);
}
- public object Lookup (string name)
- {
- return defined_names [name];
- }
-
static public ArrayList UserDefinedNamespaces {
get {
return all_namespaces;
}
}
+ public override string FullName {
+ get {
+ return fullname;
+ }
+ }
+
/// <summary>
/// The parent of this namespace, used by the parser to "Pop"
/// the current namespace declaration
else
return String.Format ("Namespace ({0})", Name);
}
+
+ bool IAlias.IsType {
+ get { return false; }
+ }
+
+ TypeExpr IAlias.ResolveAsType (EmitContext ec)
+ {
+ throw new InvalidOperationException ();
+ }
}
public class NamespaceEntry
// exist.
//
public class UsingEntry {
- public readonly string Name;
+ public Expression Name;
public readonly NamespaceEntry NamespaceEntry;
public readonly Location Location;
- public UsingEntry (NamespaceEntry entry, string name, Location loc)
+ public UsingEntry (NamespaceEntry entry, Expression name, Location loc)
{
Name = name;
NamespaceEntry = entry;
Location = loc;
}
- Namespace resolved_ns;
+ internal FullNamedExpression resolved;
public Namespace Resolve ()
{
- if (resolved_ns != null)
- return resolved_ns;
-
- Namespace curr_ns = NamespaceEntry.NS;
- while ((curr_ns != null) && (resolved_ns == null)) {
- resolved_ns = curr_ns.GetNamespace (Name, false);
+ if (resolved != null)
+ return resolved as Namespace;
- if (resolved_ns == null)
- curr_ns = curr_ns.Parent;
- }
+ DeclSpace root = RootContext.Tree.Types;
+ root.NamespaceEntry = NamespaceEntry;
+ resolved = Name.ResolveAsTypeStep (root.EmitContext);
+ root.NamespaceEntry = null;
- return resolved_ns;
+ return resolved as Namespace;
}
}
Location = loc;
}
- object resolved;
+ FullNamedExpression resolved;
- public object Resolve ()
+ public FullNamedExpression Resolve ()
{
if (resolved != null)
return resolved;
- NamespaceEntry curr_ns = NamespaceEntry;
-
- string alias = Alias.ToString ();
- while ((curr_ns != null) && (resolved == null)) {
- resolved = curr_ns.Lookup (null, alias, false, Location);
-
- if (resolved == null)
- curr_ns = curr_ns.Parent;
- }
+ DeclSpace root = RootContext.Tree.Types;
+ root.NamespaceEntry = NamespaceEntry;
+ resolved = Alias.ResolveAsTypeStep (root.EmitContext);
+ root.NamespaceEntry = null;
return resolved;
}
}
public NamespaceEntry (NamespaceEntry parent, SourceFile file, string name, Location loc)
- : this (parent, file, name, false, loc)
- { }
-
- protected NamespaceEntry (NamespaceEntry parent, SourceFile file, string name, bool is_implicit, Location loc)
{
this.parent = parent;
this.file = file;
- this.IsImplicit = is_implicit;
+ this.IsImplicit = false;
this.ID = ++next_id;
- if (!is_implicit && (parent != null))
+ if (parent != null)
ns = parent.NS.GetNamespace (name, true);
else if (name != null)
ns = Namespace.LookupNamespace (name, true);
else
ns = Namespace.Root;
ns.AddNamespaceEntry (this);
+ this.FullName = ns.Name;
+ }
- if ((parent != null) && (parent.NS != ns.Parent))
- implicit_parent = new NamespaceEntry (parent, file, ns.Parent.Name, true, loc);
- else
- implicit_parent = parent;
+ private NamespaceEntry (NamespaceEntry parent, SourceFile file, Namespace ns)
+ {
+ this.parent = parent;
+ this.file = file;
+ this.IsImplicit = true;
+ this.ID = ++next_id;
+ this.ns = ns;
this.FullName = ns.Name;
}
+ //
+ // According to section 16.3.1 (using-alias-directive), the namespace-or-type-name is
+ // resolved as if the immediately containing namespace body has no using-directives.
+ //
+ // Section 16.3.2 says that the same rule is applied when resolving the namespace-name
+ // in the using-namespace-directive.
+ //
+ // To implement these rules, the expressions in the using directives are resolved using
+ // the "doppelganger" (ghostly bodiless duplicate).
+ //
+ NamespaceEntry doppelganger;
+ NamespaceEntry Doppelganger {
+ get {
+ if (!IsImplicit && doppelganger == null)
+ doppelganger = new NamespaceEntry (ImplicitParent, file, ns);
+ return doppelganger;
+ }
+ }
+
static int next_id = 0;
public readonly string FullName;
public readonly int ID;
public NamespaceEntry ImplicitParent {
get {
+ if (parent == null)
+ return null;
+ if (implicit_parent == null) {
+ implicit_parent = (parent.NS == ns.Parent)
+ ? parent
+ : new NamespaceEntry (parent, file, ns.Parent);
+ }
return implicit_parent;
}
}
- public void DefineName (string name, object o)
+ public void DefineName (string name, IAlias o)
{
ns.DefineName (name, o);
}
/// <summary>
/// Records a new namespace for resolving name references
/// </summary>
- public void Using (string ns, Location loc)
+ public void Using (Expression ns, Location loc)
{
+ string name = ns.ToString ();
if (DeclarationFound){
Report.Error (1529, loc, "A using clause must precede all other namespace elements");
return;
}
- if (ns == FullName)
+ if (name == FullName)
return;
if (using_clauses == null)
using_clauses = new ArrayList ();
- foreach (UsingEntry old_entry in using_clauses){
- if (old_entry.Name == ns){
- Report.Warning (105, loc, "The using directive for '" + ns +
- "' appeared previously in this namespace");
+ foreach (UsingEntry old_entry in using_clauses) {
+ if (old_entry.Name.ToString () == name) {
+ if (RootContext.WarningLevel >= 3)
+ Report.Warning (105, loc, "The using directive for '{0}' appeared previously in this namespace", name);
return;
}
}
-
- UsingEntry ue = new UsingEntry (this, ns, loc);
+
+
+ UsingEntry ue = new UsingEntry (Doppelganger, ns, loc);
using_clauses.Add (ue);
}
- public void UsingAlias (string alias, Expression namespace_or_type, Location loc)
+ public void UsingAlias (string name, Expression alias, Location loc)
{
+ if (DeclarationFound){
+ Report.Error (1529, loc, "A using clause must precede all other namespace elements");
+ return;
+ }
+
if (aliases == null)
aliases = new Hashtable ();
- if (aliases.Contains (alias)){
- Report.Error (1537, loc, "The using alias `" + alias +
+ if (aliases.Contains (name)){
+ Report.Error (1537, loc, "The using alias `" + name +
"' appeared previously in this namespace");
return;
}
- aliases [alias] = new AliasEntry (this, alias, namespace_or_type, loc);
+ aliases [name] = new AliasEntry (Doppelganger, name, alias, loc);
}
- protected AliasEntry GetAliasEntry (string alias)
+ public FullNamedExpression LookupAlias (string alias)
{
AliasEntry entry = null;
-
if (aliases != null)
entry = (AliasEntry) aliases [alias];
- if (entry == null && Parent != null)
- entry = Parent.GetAliasEntry (alias);
- return entry;
+ return entry == null ? null : entry.Resolve ();
}
- public string LookupAlias (string alias)
+ public FullNamedExpression LookupNamespaceOrType (DeclSpace ds, string name, Location loc)
{
- AliasEntry entry = GetAliasEntry (alias);
+ FullNamedExpression resolved = null;
+ string rest = null;
- if (entry == null)
- return null;
-
- object resolved = entry.Resolve ();
- if (resolved == null)
- return null;
- else if (resolved is Namespace)
- return ((Namespace) resolved).Name;
- else
- return ((Type) resolved).FullName;
- }
-
- public object Lookup (DeclSpace ds, string name, bool silent, Location loc)
- {
- object o;
- Namespace ns;
-
- //
// If name is of the form `N.I', first lookup `N', then search a member `I' in it.
- //
int pos = name.IndexOf ('.');
if (pos >= 0) {
- string first = name.Substring (0, pos);
- string last = name.Substring (pos + 1);
+ rest = name.Substring (pos + 1);
+ name = name.Substring (0, pos);
+ }
- o = Lookup (ds, first, silent, loc);
- if (o == null)
- return null;
+ for (NamespaceEntry curr_ns = this; curr_ns != null; curr_ns = curr_ns.ImplicitParent) {
+ if ((resolved = curr_ns.Lookup (ds, name, loc)) != null)
+ break;
+ }
- ns = o as Namespace;
- if (ns != null)
- return ns.Lookup (ds, last);
+ if (resolved == null || rest == null)
+ return resolved;
- Type nested = TypeManager.LookupType ((((Type) o).Name + "." + last));
- if ((nested == null) || ((ds != null) && !ds.CheckAccessLevel (nested)))
- return null;
+ Namespace ns = resolved as Namespace;
+ if (ns != null)
+ return ns.Lookup (ds, rest, loc);
- return nested;
- }
+ Type nested = TypeManager.LookupType (resolved.FullName + "." + rest);
+ if ((nested == null) || ((ds != null) && !ds.CheckAccessLevel (nested)))
+ return null;
+
+ return new TypeExpression (nested, Location.Null);
+ }
+
+ private FullNamedExpression Lookup (DeclSpace ds, string name, Location loc)
+ {
+ // Precondition: Only simple names (no dots) will be looked up with this function.
//
- // Check whether it's a namespace.
+ // Check whether it's in the namespace.
//
- o = NS.Lookup (ds, name);
+ FullNamedExpression o = NS.Lookup (ds, name, loc);
if (o != null)
return o;
+ if (IsImplicit)
+ return null;
+
//
// Check aliases.
//
- AliasEntry entry = GetAliasEntry (name);
- if (entry != null) {
- o = entry.Resolve ();
- if (o != null)
- return o;
- }
-
- if (name.IndexOf ('.') > 0)
- return null;
+ o = LookupAlias (name);
+ if (o != null)
+ return o;
//
// Check using entries.
//
- Type t = null, match = null;
+ FullNamedExpression t = null, match = null;
foreach (Namespace using_ns in GetUsingTable ()) {
- match = using_ns.Lookup (ds, name) as Type;
- if (match != null){
+ match = using_ns.Lookup (ds, name, loc);
+ if ((match != null) && (match is TypeExpr)) {
if (t != null) {
- if (!silent)
- DeclSpace.Error_AmbiguousTypeReference (loc, name, t, match);
+ DeclSpace.Error_AmbiguousTypeReference (loc, name, t.FullName, match.FullName);
return null;
} else {
t = match;
{
if (namespace_using_table != null)
return namespace_using_table;
-
- if (using_clauses == null)
- return new Namespace [0];
+
+ if (using_clauses == null) {
+ namespace_using_table = new Namespace [0];
+ return namespace_using_table;
+ }
ArrayList list = new ArrayList (using_clauses.Count);
if (using_clauses != null) {
using_list = new string [using_clauses.Count];
for (int i = 0; i < using_clauses.Count; i++)
- using_list [i] = ((UsingEntry) using_clauses [i]).Name;
+ using_list [i] = ((UsingEntry) using_clauses [i]).Name.ToString ();
} else {
using_list = new string [0];
}
int parent_id = parent != null ? parent.symfile_id : 0;
- symfile_id = symwriter.DefineNamespace (ns.Name, file, using_list, parent_id);
+ if (file.SourceFileEntry == null)
+ return;
+
+ symfile_id = symwriter.DefineNamespace (
+ ns.Name, file.SourceFileEntry, using_list, parent_id);
}
public int SymbolFileID {
}
}
- static void Msgtry (string s)
+ static void MsgtryRef (string s)
{
Console.WriteLine (" Try using -r:" + s);
}
+
+ static void MsgtryPkg (string s)
+ {
+ Console.WriteLine (" Try using -pkg:" + s);
+ }
protected void error246 (Location loc, string name)
{
- if (TypeManager.LookupType (name) != null)
- Report.Error (138, loc, "The using keyword only lets you specify a namespace, " +
- "`" + name + "' is a class not a namespace.");
- else {
- Report.Error (246, loc, "The namespace `" + name +
- "' can not be found (missing assembly reference?)");
-
- switch (name){
- case "Gtk": case "GtkSharp":
- Msgtry ("gtk-sharp");
- break;
-
- case "Gdk": case "GdkSharp":
- Msgtry ("gdk-sharp");
- break;
-
- case "Glade": case "GladeSharp":
- Msgtry ("glade-sharp");
- break;
-
- case "System.Drawing":
- Msgtry ("System.Drawing");
- break;
-
- case "System.Web.Services":
- Msgtry ("System.Web.Services");
- break;
-
- case "System.Web":
- Msgtry ("System.Web");
- break;
-
- case "System.Data":
- Msgtry ("System.Data");
- break;
-
- case "System.Windows.Forms":
- Msgtry ("System.Windows.Forms");
- break;
- }
+ Report.Error (246, loc, "The namespace `" + name +
+ "' can not be found (missing assembly reference?)");
+
+ switch (name) {
+ case "Gtk": case "GtkSharp":
+ MsgtryPkg ("gtk-sharp");
+ break;
+
+ case "Gdk": case "GdkSharp":
+ MsgtryPkg ("gdk-sharp");
+ break;
+
+ case "Glade": case "GladeSharp":
+ MsgtryPkg ("glade-sharp");
+ break;
+
+ case "System.Drawing":
+ case "System.Web.Services":
+ case "System.Web":
+ case "System.Data":
+ case "System.Windows.Forms":
+ MsgtryRef (name);
+ break;
}
}
if (ue.Resolve () != null)
continue;
- error246 (ue.Location, ue.Name);
+ if (ue.resolved == null)
+ error246 (ue.Location, ue.Name.ToString ());
+ else
+ Report.Error (138, ue.Location, "The using keyword only lets you specify a namespace, " +
+ "`" + ue.Name + "' is a class not a namespace.");
+
}
}