public Expression CompileCall(AstCall e)
        {
            // Builtin struct initialization
            if (e.Base is AstBuiltinType)
            {
                var dt = NameResolver.GetType(Namescope, e.Base);

                if (dt.IsStruct)
                {
                    // Default ctor
                    if (e.Arguments.Count == 0)
                    {
                        return(new Default(e.Source, dt));
                    }

                    dt.PopulateMembers();

                    Constructor  ctor;
                    Expression[] args;
                    return(TryResolveConstructorOverload(e.Source, dt.Constructors, e.Arguments, out ctor, out args)
                        ? new NewObject(e.Source, ctor, args)
                        : Error(e.Source, ErrorCode.E3125, dt.Quote() + " has no constructors matching the argument list " +
                                PrintableArgumentList(e.Arguments) +
                                NameResolver.SuggestCandidates(dt.Constructors)));
                }

                return(Error(e.Source, ErrorCode.E3126, dt.Quote() + " must be instantiated using 'new' because it is not a struct"));
            }

            var pe = ResolveExpression(e.Base, null);

            switch (pe.ExpressionType)
            {
            case PartialExpressionType.Block:
            case PartialExpressionType.Type:
            case PartialExpressionType.Namespace:
                if (e.Base is AstIdentifier)
                {
                    var p2 = NameResolver.TryResolveUsingType(Namescope, e.Base as AstIdentifier, null);
                    if (p2 != null)
                    {
                        pe = p2;
                    }
                }
                break;
            }

            var sym = CompilePartial(pe);

            if (sym.IsInvalid)
            {
                return(Expression.Invalid);
            }

            // Delegate call
            if (sym.ReturnType.IsDelegate)
            {
                var dt = (DelegateType)sym.ReturnType;
                dt.AssignBaseType();
                var args = TryApplyDefaultValuesOnArgumentList(sym.Source, dt.Parameters, CompileArgumentList(e.Arguments));
                return(TryApplyImplicitCastsOnArgumentList(dt.Parameters, args)
                    ? new CallDelegate(e.Source, sym, args)
                    : Error(e.Source, ErrorCode.E3127, "Call to delegate of type " + dt.Quote() + " has some invalid arguments " +
                            PrintableArgumentList(e.Arguments)));
            }

            // Using static fall back
            if (!(sym is MethodGroup) && e.Base is AstIdentifier)
            {
                var p2 = NameResolver.TryResolveUsingType(Namescope, e.Base as AstIdentifier, null);
                if (p2 != null)
                {
                    sym = CompilePartial(p2);
                    if (sym.IsInvalid)
                    {
                        return(Expression.Invalid);
                    }
                }
            }

            // Method call
            if (sym is MethodGroup)
            {
                var g = sym as MethodGroup;

                Method       method;
                Expression[] args;
                return(TryResolveMethodOverload(e.Source, g.Candidates, e.Arguments, out method, out args)
                    ? (g.IsQualified && g.Object != null && method.IsStatic
                            ? Error(sym.Source, ErrorCode.E3123, method.Quote() + " is static -- qualify with the type name") :
                       g.Object == null && !method.IsStatic
                            ? Error(sym.Source, ErrorCode.E3124, method.Quote() + " is non-static and cannot be accessed from a static context")
                            : new CallMethod(e.Source, method.IsStatic ? null : g.Object, method, args))
                    : g.Candidates.Count == 1
                        ? Error(e.Source, ErrorCode.E3128, "Call to " + g.Candidates[0].Quote() + " has some invalid arguments " +
                                PrintableArgumentList(e.Arguments))
                        : Error(e.Source, ErrorCode.E3129, "No overloads of " + g.CandidatesBaseName.Quote() + " matches the argument list " +
                                PrintableArgumentList(e.Arguments) +
                                NameResolver.SuggestCandidates(g.Candidates)));
            }

            // Extension method call
            if (sym is ExtensionGroup)
            {
                var g = sym as ExtensionGroup;

                Method       method;
                Expression[] args;
                var          astArgs = new AstArgument[e.Arguments.Count + 1];
                astArgs[0] = new AstIL(g.Object);
                for (int i = 0; i < e.Arguments.Count; i++)
                {
                    astArgs[i + 1] = e.Arguments[i];
                }

                return(TryResolveMethodOverload(e.Source, g.Candidates, astArgs, out method, out args)
                    ? new CallMethod(e.Source, null, method, args)
                    : g.Candidates.Count == 1
                        ? Error(e.Source, ErrorCode.E3128, "Call to " + g.Candidates[0].Quote() + " has some invalid arguments " +
                                PrintableArgumentList(astArgs))
                        : Error(e.Source, ErrorCode.E3129, "No overloads of " + g.CandidatesBaseName.Quote() + " matches the argument list " +
                                PrintableArgumentList(e.Arguments) +
                                NameResolver.SuggestCandidates(g.Candidates)));
            }

            return(Error(e.Source, ErrorCode.E3130, "Instances of type " + sym.ReturnType.Quote() + " cannot be called as a function"));
        }
        public PartialExpression ResolveIdentifier(AstIdentifier id, int?typeParamCount)
        {
            if (typeParamCount == null)
            {
                var pi = TryResolveLocalIdentifier(id);
                if (pi != null)
                {
                    return(pi);
                }
            }

            // Parent scope is resolved later
            Namescope parentScope;

            if (IsFunctionScope)
            {
                var dt = Namescope as DataType;

                // Should not happen
                if (dt == null)
                {
                    return(PartialError(id.Source, ErrorCode.I0000, "Namescope was a Function without DataType in ResolveIdentifier()"));
                }

                // Check if it as a member of the class
                var obj = Function != null && !Function.IsStatic
                    ? new This(id.Source, TypeBuilder.Parameterize(Function.DeclaringType)).Address
                    : null;

                var p = TryResolveTypeMember(dt, id, typeParamCount, null, obj);
                if (p != null)
                {
                    return(p);
                }

                // Check if it is a member of the parent class
                parentScope = dt.Parent;
                var parentType = dt.ParentType;

                while (parentType != null)
                {
                    p = TryResolveTypeMember(parentType, id, typeParamCount, null, obj);
                    if (p != null)
                    {
                        return(p);
                    }

                    parentScope = parentType.Parent;
                    parentType  = parentType.ParentType;
                }
            }
            else
            {
                // Check if it is a meta property protected by a req statement
                if (MetaProperty != null && typeParamCount == null)
                {
                    foreach (var req in ReqStatements)
                    {
                        if (req is ReqProperty)
                        {
                            var rmp = req as ReqProperty;
                            if (rmp.PropertyName == id.Symbol && rmp.PropertyType != null)
                            {
                                return(new PartialValue(new GetMetaProperty(id.Source, rmp.PropertyType, rmp.PropertyName)));
                            }
                        }
                    }
                }

                var block = Namescope as BlockBase;

                if (block != null)
                {
                    if (typeParamCount == null)
                    {
                        var p  = TryResolveCapturedLocalIdentifier(block, id);
                        var mp = NameResolver.TryGetMetaProperty(id.Source, block, block, id.Symbol, true);

                        if (p != null && mp != null)
                        {
                            Log.Error(id.Source, ErrorCode.E0000, id.Symbol.Quote() + " is an ambiguous match between meta property and captured local variable. Use 'meta " + id.Symbol + "' or 'local::" + id.Symbol + "' to disambiguate");
                        }
                        if (p != null)
                        {
                            return(p);
                        }
                        if (mp != null)
                        {
                            return(new PartialValue(new GetMetaProperty(id.Source, mp.ReturnType, mp.Name)));
                        }
                    }

                    var dt = block.TryFindTypeParent();

                    if (dt != null)
                    {
                        var p = TryResolveTypeMember(dt, id, typeParamCount, null, new GetMetaObject(id.Source, TypeBuilder.Parameterize(dt)));
                        if (p != null)
                        {
                            return(p);
                        }
                    }
                }

                parentScope = Namescope;
            }

            if (parentScope != null)
            {
                // Check if it is a member of the parent namespace
                var p = NameResolver.TryResolveMemberRecursive(parentScope, id, typeParamCount);
                if (p != null)
                {
                    return(p);
                }

                // Check if it is a member in a namespace referenced from a using-directive
                p = NameResolver.TryResolveUsingNamespace(parentScope, id, typeParamCount);
                if (p != null)
                {
                    return(p);
                }

                // Check if it is a static method in a class referenced from a using static-directive
                p = NameResolver.TryResolveUsingType(parentScope, id, typeParamCount);
                if (p != null)
                {
                    return(p);
                }
            }

            return(PartialError(id.Source, ErrorCode.E3102, this.GetUnresolvedIdentifierError(id, typeParamCount)));
        }