// --------------------------------------------------------------------------- // Copyright (C) 2006 Microsoft Corporation All Rights Reserved // --------------------------------------------------------------------------- using System.CodeDom; using System.Collections; using System.Collections.Generic; using System.Globalization; using System.Reflection; using System.Text; namespace System.Workflow.Activities.Rules { internal abstract class Symbol { internal abstract string Name { get; } internal abstract CodeExpression ParseRootIdentifier(Parser parser, ParserContext parserContext, bool assignIsEquality); internal abstract void RecordSymbol(ArrayList list); } // Represents a field, property, or method within "this". (Not a nested type.) internal class MemberSymbol : Symbol { private MemberInfo member; internal MemberSymbol(MemberInfo member) { this.member = member; } internal override string Name { get { return member.Name; } } internal override CodeExpression ParseRootIdentifier(Parser parser, ParserContext parserContext, bool assignIsEquality) { return parser.ParseUnadornedMemberIdentifier(parserContext, this, assignIsEquality); } internal override void RecordSymbol(ArrayList list) { list.Add(member); } } internal class NamespaceSymbol : Symbol { private string name; internal readonly NamespaceSymbol Parent; internal Dictionary NestedSymbols; internal readonly int Level; internal NamespaceSymbol(string name, NamespaceSymbol parent) { this.name = name; this.Parent = parent; this.Level = (parent == null) ? 0 : parent.Level + 1; } // For unnamed namespaces. There is only one of these. internal NamespaceSymbol() { } internal override string Name { get { return name; } } internal NamespaceSymbol AddNamespace(string nsName) { if (NestedSymbols == null) NestedSymbols = new Dictionary(); Symbol ns = null; if (!NestedSymbols.TryGetValue(nsName, out ns)) { ns = new NamespaceSymbol(nsName, this); NestedSymbols.Add(nsName, ns); } return ns as NamespaceSymbol; } internal void AddType(Type type) { TypeSymbol typeSym = new TypeSymbol(type); string typeName = typeSym.Name; if (NestedSymbols == null) NestedSymbols = new Dictionary(); Symbol existingSymbol = null; if (NestedSymbols.TryGetValue(typeName, out existingSymbol)) { OverloadedTypeSymbol overloadSym = existingSymbol as OverloadedTypeSymbol; if (overloadSym == null) { TypeSymbol typeSymbol = existingSymbol as TypeSymbol; System.Diagnostics.Debug.Assert(typeSymbol != null); overloadSym = new OverloadedTypeSymbol(typeName, typeSym, typeSymbol); NestedSymbols[typeName] = overloadSym; } else { overloadSym.AddLocalType(typeSym); } } else { NestedSymbols.Add(typeName, typeSym); } } internal Symbol FindMember(string memberName) { Symbol nestedSym = null; NestedSymbols.TryGetValue(memberName, out nestedSym); return nestedSym; } internal ArrayList GetMembers() { ArrayList members = new ArrayList(NestedSymbols.Count); foreach (Symbol sym in NestedSymbols.Values) sym.RecordSymbol(members); return members; } internal string GetQualifiedName() { StringBuilder sb = new StringBuilder(); Stack names = new Stack(); names.Push(Name); for (NamespaceSymbol currentParent = Parent; currentParent != null; currentParent = currentParent.Parent) names.Push(currentParent.Name); sb.Append(names.Pop()); while (names.Count > 0) { sb.Append('.'); sb.Append(names.Pop()); } return sb.ToString(); } internal override CodeExpression ParseRootIdentifier(Parser parser, ParserContext parserContext, bool assignIsEquality) { return parser.ParseRootNamespaceIdentifier(parserContext, this, assignIsEquality); } internal override void RecordSymbol(ArrayList list) { // Just add the name (string) to the member list. list.Add(Name); } } internal abstract class TypeSymbolBase : Symbol { internal abstract OverloadedTypeSymbol OverloadType(TypeSymbolBase typeSymBase); } internal class TypeSymbol : TypeSymbolBase { internal readonly Type Type; internal readonly int GenericArgCount; private string name; internal TypeSymbol(Type type) { this.Type = type; this.name = type.Name; if (type.IsGenericType) { int tickIx = type.Name.LastIndexOf('`'); if (tickIx > 0) { string count = type.Name.Substring(tickIx + 1); GenericArgCount = Int32.Parse(count, CultureInfo.InvariantCulture); name = type.Name.Substring(0, tickIx); } } } internal override string Name { get { return name; } } internal override OverloadedTypeSymbol OverloadType(TypeSymbolBase newTypeSymBase) { OverloadedTypeSymbol newTypeOverload = newTypeSymBase as OverloadedTypeSymbol; if (newTypeOverload != null) { // We've encountered an overloaded type symbol over a previous simple // type symbol. return newTypeOverload.OverloadType(this); } else { // We've encountered two simple types... just create an overload for them if // possible. TypeSymbol newTypeSym = newTypeSymBase as TypeSymbol; if (newTypeSym != null && this.CanOverload(newTypeSym)) return new OverloadedTypeSymbol(name, this, newTypeSym); } return null; } internal bool CanOverload(TypeSymbol typeSym) { return typeSym.GenericArgCount != this.GenericArgCount; } internal override CodeExpression ParseRootIdentifier(Parser parser, ParserContext parserContext, bool assignIsEquality) { // The root name is a type (might be generic or not). return parser.ParseRootTypeIdentifier(parserContext, this, assignIsEquality); } internal override void RecordSymbol(ArrayList list) { // Add the System.Type to the member list. list.Add(Type); } } internal class OverloadedTypeSymbol : TypeSymbolBase { internal List TypeSymbols = new List(); private string name; internal OverloadedTypeSymbol(string name, TypeSymbol typeSym1, TypeSymbol typeSym2) { this.name = name; AddLocalType(typeSym1); AddLocalType(typeSym2); } private OverloadedTypeSymbol(string name, List typeSymbols) { this.name = name; this.TypeSymbols = typeSymbols; } internal override string Name { get { return name; } } // Add a local overload (within the same namespace). internal void AddLocalType(TypeSymbol typeSym) { // Since it's a local overload, we don't have to check whether it's ambiguous. TypeSymbols.Add(typeSym); } internal override OverloadedTypeSymbol OverloadType(TypeSymbolBase newTypeSymBase) { List newOverloads = new List(); TypeSymbol typeSym = null; OverloadedTypeSymbol newTypeOverload = newTypeSymBase as OverloadedTypeSymbol; if (newTypeOverload != null) { newOverloads.AddRange(newTypeOverload.TypeSymbols); } else { // We've encountered a simple type... just create an overload for them if // possible. typeSym = newTypeSymBase as TypeSymbol; if (typeSym != null) newOverloads.Add(typeSym); } // If every item in this overloaded type symbol is overloadable with the new one, // add to the new list all our items. foreach (TypeSymbol thisTypeSym in this.TypeSymbols) { foreach (TypeSymbol newTypeSym in newOverloads) { if (!newTypeSym.CanOverload(thisTypeSym)) return null; // Can't overload } newOverloads.Add(thisTypeSym); } return new OverloadedTypeSymbol(name, newOverloads); } internal override CodeExpression ParseRootIdentifier(Parser parser, ParserContext parserContext, bool assignIsEquality) { return parser.ParseRootOverloadedTypeIdentifier(parserContext, this.TypeSymbols, assignIsEquality); } internal override void RecordSymbol(ArrayList list) { foreach (TypeSymbol overloadedType in TypeSymbols) list.Add(overloadedType.Type); } } }