public override Node Analyze(AffeCompilerState state) { BindingFlags isstatic = BindingFlags.Instance; Type etype = state.CheckForTypeExpression(this.Expression); if (etype == null) { this.Expression = (Expression) this.Expression.Analyze(state); etype = this.Expression.Type; } else { isstatic = BindingFlags.Static; } for (int i = 0; i < this.Index.Count; i++) this.Index[i] = (Expression) this.Index[i].Analyze(state); if (etype.IsArray) { if (this.Index.Count != this.Expression.Type.GetArrayRank()) throw new AffeException("Array must be indexed with the correct rank.", this); if (isstatic == BindingFlags.Static) throw new AffeException("Cannot statically index an array.", this); for (int i = 0; i < this.Index.Count; i++) this.Index[i] = state.CastTo(this.Index[i], typeof(int)); this.Type = etype.GetElementType(); } else { object[] attrs = etype.GetCustomAttributes(typeof(DefaultMemberAttribute), true); if (attrs.Length == 0) throw new AffeException("That object type cannot be indexed.", this.Expression); DefaultMemberAttribute attr = (DefaultMemberAttribute) attrs[0]; PropertyInfo pi = etype.GetProperty(attr.MemberName, isstatic | BindingFlags.Public | BindingFlags.FlattenHierarchy); if (pi == null) throw new AffeException("Cannot find indexer on that type.", this.Expression); this.Type = pi.PropertyType; Type[] indexTypes; if (pi.GetGetMethod() != null) { ParameterInfo[] param = pi.GetGetMethod().GetParameters(); indexTypes = new Type[param.Length]; for (int i = 0; i < param.Length; i++) indexTypes[i] = param[i].ParameterType; } else { ParameterInfo[] param = pi.GetSetMethod().GetParameters(); indexTypes = new Type[param.Length - 1]; for (int i = 0; i < param.Length - 1; i++) indexTypes[i] = param[i].ParameterType; } if (this.Index.Count != indexTypes.Length) throw new AffeException("Incorrect parameter count to indexer.", this); for (int i = 0; i < indexTypes.Length; i++) this.Index[i] = state.CastTo(this.Index[i], indexTypes[i]); this.mIndexer = pi; } return this; }
public override Node Analyze(AffeCompilerState state) { BindingFlags isstatic = BindingFlags.Instance; // Check for static calls. Type target = state.CheckForTypeExpression(this.Target); // If it's not a type, consider it an expression. if (target == null) { this.Target = (Expression) this.Target.Analyze(state); target = this.Target.Type; } else { isstatic = BindingFlags.Static; } Type[] types = new Type[this.Arguments.Count]; for (int i = 0; i < types.Length; i++) { this.Arguments[i] = (Expression) this.Arguments[i].Analyze(state); types[i] = this.Arguments[i].Type; } MethodInfo mi; try { mi = target.GetMethod(this.Name.Name, isstatic | BindingFlags.Public | BindingFlags.FlattenHierarchy, null, types, null); } catch (AmbiguousMatchException) { throw new AffeException("Method call is ambiguous.", this); } catch (Exception) { mi = null; } if (mi == null) throw new AffeException("Method not found on class.", this); // GetMethod will return the closest match it can, not an exact // match. This is nifty. Now we just have to cast where // appropriate. ParameterInfo[] param = mi.GetParameters(); for (int i = 0; i < this.Arguments.Count; i++) { this.Arguments[i] = state.CastTo(this.Arguments[i], param[i].ParameterType); } this.MethodInfo = mi; this.Type = mi.ReturnType; return this; }
public override Node Analyze(AffeCompilerState state) { BindingFlags isstatic = BindingFlags.Instance; // Check for static calls. Type target = state.CheckForTypeExpression(this.Target); // If it's not a type, consider it an expression. if (target == null) { this.Target = (Expression) this.Target.Analyze(state); target = this.Target.Type; } else { isstatic = BindingFlags.Static; } MemberInfo mi; try { MemberInfo[] mis = target.GetMember(this.Member.Name, MemberTypes.Field | MemberTypes.Property, isstatic | BindingFlags.Public | BindingFlags.FlattenHierarchy); if (mis.Length > 1) throw new AmbiguousMatchException(); if (mis.Length == 0) throw new ArgumentException(); mi = mis[0]; } catch (Exception) { mi = null; } if (mi == null) throw new AffeException("Member not found on class.", this); if (mi is PropertyInfo) { this.Type = ((PropertyInfo) mi).PropertyType; } else { this.Type = ((FieldInfo) mi).FieldType; } this.MemberInfo = mi; return this; }