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;
        }