/// <summary>
        /// Gets a member access object representing the a member access.
        /// </summary>
        /// <param name="node"></param>
        /// <param name="ctx"></param>
        /// <param name="varExp"></param>
        /// <param name="memberName"></param>
        /// <returns></returns>
        public static MemberAccess GetMemberAccess(AstNode node, Context ctx, Expr varExp, string memberName)
        {
            bool   isVariableExp = varExp is VariableExpr;
            string variableName  = isVariableExp ? ((VariableExpr)varExp).Name : string.Empty;

            // CASE 1: External function call "user.create"
            if (isVariableExp && FunctionHelper.IsExternalFunction(ctx.ExternalFunctions, variableName, memberName))
            {
                return new MemberAccess(MemberMode.FunctionExternal)
                       {
                           Name = variableName, MemberName = memberName
                       }
            }
            ;

            // CASE 2. Static method call: "Person.Create"
            if (isVariableExp)
            {
                var result = MemberHelper.IsExternalTypeName(ctx.Memory, ctx.Types, variableName);

                if (result.Success)
                {
                    return(MemberHelper.GetExternalTypeMember(node, (Type)result.Item, variableName, null, memberName, true));
                }
            }

            var obj = varExp.Evaluate() as LObject;

            // Check for empty objects.
            ExceptionHelper.NotNull(node, obj, "member access");

            var type = obj.Type;

            // Case 3: Method / Property on FluentScript type
            bool isCoreType = obj.Type.IsBuiltInType();

            if (isCoreType)
            {
                var result = MemberHelper.GetLangBasicTypeMember(node, ctx.Methods, obj, memberName);
                return(result);
            }

            // CASE 4: Method / Property on External/Host language type (C#)
            var lclass     = obj as LClass;
            var lclassType = lclass.Type as LClassType;
            var member     = MemberHelper.GetExternalTypeMember(node, lclassType.DataType, variableName, lclass.Value, memberName, false);

            return(member);
        }
        /// <summary>
        /// Gets a member access object representing the a member access.
        /// </summary>
        /// <param name="node"></param>
        /// <param name="ctx"></param>
        /// <param name="varExp"></param>
        /// <param name="memberName"></param>
        /// <returns></returns>
        public static MemberAccess GetMemberAccess(AstNode node, Context ctx, Expr varExp, string memberName, IAstVisitor visitor)
        {
            var isVariableExp = varExp.IsNodeType(NodeTypes.SysVariable);
            var variableName  = isVariableExp ? ((VariableExpr)varExp).Name : string.Empty;

            // CASE 1: External function call "user.create"
            if (isVariableExp && FunctionHelper.IsExternalFunction(ctx.ExternalFunctions, variableName, memberName))
            {
                return new MemberAccess(MemberMode.FunctionExternal)
                       {
                           Name = variableName, MemberName = memberName
                       }
            }
            ;

            // CASE 2. Static method call: "Person.Create"
            if (isVariableExp)
            {
                var result = MemberHelper.IsExternalTypeName(ctx.Memory, ctx.Types, variableName);

                if (result.Success)
                {
                    return(MemberHelper.GetExternalTypeMember(node, (Type)result.Item, variableName, null, memberName, true));
                }
            }

            // CASE 3: Module
            if (varExp.IsNodeType(NodeTypes.SysVariable))
            {
                var name = varExp.ToQualifiedName();
                if (!ctx.Memory.Contains(name))
                {
                    var modresult = ResolveSymbol(varExp.SymScope, name);
                    if (modresult != null)
                    {
                        return(modresult);
                    }
                }
            }

            // CASE 4: Nested member.
            var res = varExp.Visit(visitor);

            if (res is MemberAccess)
            {
                return(res as MemberAccess);
            }

            var obj = res as LObject;

            // Check for empty objects.
            ExceptionHelper.NotNull(node, obj, "member access");

            var type = obj.Type;

            // Case 3: Method / Property on FluentScript type
            var isCoreType = obj.Type.IsBuiltInType();

            if (isCoreType)
            {
                var result = MemberHelper.GetLangBasicTypeMember(node, ctx.Methods, obj, memberName);
                return(result);
            }

            // CASE 4: Method / Property on External/Host language type (C#)
            var lclass     = obj as LClass;
            var lclassType = lclass.Type as LClassType;
            var member     = MemberHelper.GetExternalTypeMember(node, lclassType.DataType, variableName, lclass.Value, memberName, false);

            return(member);
        }