The StaDyn Programming Language
Source code documentation of StaDyn, a hybrid static and dynamic typing language.
GetMembersOperation.cs
Go to the documentation of this file.
1 // -------------------------------------------------------------------------- //
3 // Project rROTOR //
4 // -------------------------------------------------------------------------- //
5 // File: GetMembers.cs //
6 // Authors: Francisco Ortin - francisco.ortin@gmail.com //
7 // Description: //
8 // Represents an operation to return all the members in a type. //
9 // Inheritance: Type System Operation. //
10 // Implements Double Dispatch Pattern. //
11 // -------------------------------------------------------------------------- //
12 // Create date: 22-04-2010 //
13 // Modification date: 22-04-2010 //
15 
16 using TypeSystem;
17 using AST;
18 using ErrorManagement;
19 using System;
20 using TypeSystem.Constraints;
21 using DynVarManagement;
22 using System.Collections.Generic;
23 using System.Reflection;
24 
25 namespace TypeSystem.Operations {
30 
31  #region Fields
32  static BCLClassType arrayBCLClassType = new BCLClassType("System.Array", Type.GetType("System.Array"));
36  static AccessModifier[] emptyAccessModifier = new AccessModifier[]{};
37  static BCLClassType stringBCLClassType = new BCLClassType("System.String", Type.GetType("System.String"));
38  #endregion
39 
40  #region Constructor
42  }
43  // * We simply check if the index is promotable to an Integer.
44  #endregion
45 
46 
47  #region TypeExpression
48  public override object Exec(TypeExpression typeExpression, object arg) {
55  return emptyAccessModifier;
56  }
57  #endregion
58 
59  #region ArrayType
60  public override object Exec(ArrayType arrayType, object arg) {
61  return arrayBCLClassType.AcceptOperation(this, null);
62  }
63  #endregion
64 
65  #region StringType
66  public override object Exec(StringType stringType, object arg) {
67  return stringBCLClassType.AcceptOperation(this, null);
68  }
69  #endregion
70 
71  #region TypeVariable
72  public override object Exec(TypeVariable tv, object arg) { // this is a likely array
73  TypeExpression subtitution = tv.Substitution;
74  if (subtitution == null)
75  return emptyAccessModifier;
76  return subtitution.AcceptOperation(this, null);
77  }
78  #endregion
79 
80  #region FieldType
81  public override object Exec(FieldType g, object arg) {
82  return g.FieldTypeExpression.AcceptOperation(this, null);
83  }
84  #endregion
85 
86 
87  #region UnionType
88  public override object Exec(UnionType unionType, object arg) {
89  AccessModifier[] allMembers = emptyAccessModifier;
90  foreach (TypeExpression type in unionType.TypeSet) {
91  AccessModifier[] temp = (AccessModifier[])type.AcceptOperation(this, null);
92  allMembers = union(allMembers, temp);
93  }
94  // * Dynamic => Union of all members
95  if (unionType.IsDynamic)
96  return allMembers;
97  // * Static => Intersection of members
98  AccessModifier[] members = allMembers ;
99  foreach (TypeExpression type in unionType.TypeSet) {
100  AccessModifier[] temp = (AccessModifier[])type.AcceptOperation(this, null);
101  members = intersect(members, temp);
102  }
103  return members;
104  }
105  private static AccessModifier[] intersect(AccessModifier[] set1, AccessModifier[] set2) {
106  List<AccessModifier> list = new List<AccessModifier>();
107  foreach (AccessModifier accessModifier in set1)
108  if (contains(set2, accessModifier, ContainsStrategy.OnlyName))
109  list.Add(accessModifier);
110  AccessModifier[] result = new AccessModifier[list.Count];
111  list.CopyTo(result);
112  return result;
113  }
114  private static AccessModifier[] union(AccessModifier[] set1, AccessModifier[] set2) {
115  List<AccessModifier> list = new List<AccessModifier>();
116  list.AddRange(set1);
117  foreach (AccessModifier accessModifier in set2)
118  if (!contains(set1, accessModifier, ContainsStrategy.NameAndClass))
119  list.Add(accessModifier);
120  AccessModifier[] result = new AccessModifier[list.Count];
121  list.CopyTo(result);
122  return result;
123  }
124 
125  private enum ContainsStrategy { OnlyName, NameAndClass };
126  private static bool contains(AccessModifier[] set, AccessModifier element, ContainsStrategy strategy) {
127  foreach (AccessModifier accessModifier in set)
128  if (accessModifier.MemberIdentifier.Equals(element.MemberIdentifier))
129  if (strategy == ContainsStrategy.OnlyName)
130  return true;
131  else // Class and Name
132  if (accessModifier.Class == null || element.Class == null)
133  return true;
134  else
135  // Circle::x is different to Rectangle::x
136  if (accessModifier.Class.Name.Equals(element.Class.Name))
137  return true;
138  return false;
139  }
140  #endregion
141 
142  #region ClassType
143  public override object Exec(ClassType classType, object arg) {
144  AccessModifier[] inheritedMembers = emptyAccessModifier;
145  if (classType.BaseClass != null)
146  inheritedMembers = (AccessModifier[])classType.BaseClass.AcceptOperation(this, null);
147  AccessModifier[] members = new AccessModifier[inheritedMembers.Length + classType.Members.Count];
148  Array.Copy(inheritedMembers, 0, members, 0, inheritedMembers.Length);
149  classType.Members.Values.CopyTo(members, inheritedMembers.Length);
150  return members;
151  }
152  #endregion
153 
154  #region ClassType
155  public override object Exec(InterfaceType interfaceType, object arg) {
156  AccessModifier[] members = new AccessModifier[interfaceType.Members.Count];
157  interfaceType.Members.Values.CopyTo(members, 0);
158  foreach (InterfaceType baseType in interfaceType.InterfaceList) {
159  AccessModifier[] tempMembers = (AccessModifier[])baseType.AcceptOperation(this, null);
160  int previousLength = members.Length;
161  Array.Resize(ref members, members.Length + tempMembers.Length);
162  Array.Copy(tempMembers, 0, members, previousLength, tempMembers.Length);
163  }
164  return members;
165  }
166  #endregion
167 
168  #region BCLClassType
169  public override object Exec(BCLClassType bclClassType, object arg) {
170  // * This operation has an important performance cost. Therefore, it is done locally because
171  // the BCLClassType only returns the type of an specific member (not all of them)
172  return this.getAccessModifiers(bclClassType, false);
173  }
174  private AccessModifier[] getAccessModifiers(IBCLUserType bclUserType, bool isInterface) {
175  List<AccessModifier> list = new List<AccessModifier>();
176  Type type = Type.GetType(bclUserType.Name);
177  MemberInfo[] members = type.GetMembers(BindingFlags.Instance | BindingFlags.Public);
178  foreach (MemberInfo member in members) {
179  // * Duck typing :-)
180  IMemberType memberType = (IMemberType)bclUserType.GetType().GetMethod("FindMember").Invoke(bclUserType, new object[] { member.Name });
182  member.Name, memberType, isInterface);
183  list.Add(accessModifier);
184  }
185  AccessModifier[] result = new AccessModifier[list.Count];
186  list.CopyTo(result);
187  return result;
188  }
189  #endregion
190 
191  #region BCLInterfaceType
192  public override object Exec(BCLInterfaceType bclInterfaceType, object arg) {
193  // * This operation has an important performance cost. Therefore, it is done locally because
194  // the BCLClassType only returns the type of an specific member (not all of them)
195  return this.getAccessModifiers(bclInterfaceType, true);
196  }
197  #endregion
198 
199 
200 
201  }
202 
203 }
override object Exec(UnionType unionType, object arg)
Represents a type obtained using introspection.
Representa a union type.
Definition: UnionType.cs:36
Representa an array type.
Definition: ArrayType.cs:35
Represent a string type.
Definition: StringType.cs:36
This class represent the entry wnen sending a message to an operation object derived from TypeExpress...
string Name
Class identifier;
Definition: UserType.cs:141
Represents an operation to return all the members in a type
override object Exec(BCLClassType bclClassType, object arg)
Represents a interface type.
string MemberIdentifier
Gets the attribute name
static List< Modifier > getMethodModifierList(MethodBase method)
Gets the modifier list from a method info
override object Exec(TypeVariable tv, object arg)
Abstract class that represents all different types.
Represents a generic type expression
Definition: TypeVariable.cs:36
override object Exec(ClassType classType, object arg)
List< InterfaceType > InterfaceList
Gets the list of interfaces
Definition: UserType.cs:157
override object Exec(BCLInterfaceType bclInterfaceType, object arg)
override object Exec(FieldType g, object arg)
UserType Class
Gets or sets the class type reference
override object AcceptOperation(TypeSystemOperation op, object arg)
ClassType BaseClass
Gets the base type (null if not exists).
Definition: ClassType.cs:56
override object Exec(StringType stringType, object arg)
Association Class between ClassType and MethodType (or Fields). Represents the access modifier inform...
Represents a class type.
Definition: ClassType.cs:35
override object AcceptOperation(TypeSystemOperation op, object arg)
Definition: ClassType.cs:177
Representa a field type.
Definition: FieldType.cs:37
override object Exec(ArrayType arrayType, object arg)
override object Exec(InterfaceType interfaceType, object arg)
virtual object AcceptOperation(TypeSystemOperation op, object arg)
Representa a class attribute (fields or methods).
Definition: IMemberType.cs:32