/// <summary> /// Gets a see MemberAccess object that represents the instance, member name and other information on the member access expression. /// </summary> /// <param name="node">The Ast node associated with the member access operation</param> /// <param name="type">The data type of the external object c#.</param> /// <param name="varName">The name associated with the object. e.g. user.FirstName, "user".</param> /// <param name="obj">The object on which the member access is being performed.</param> /// <param name="memberName">The name of the member to get.</param> /// <param name="isStatic">Whether or not this is a static access.</param> /// <returns></returns> public static MemberAccess GetExternalTypeMember(AstNode node, Type type, string varName, object obj, string memberName, bool isStatic) { // 1. Get all the members on the type that match the name. var members = type.GetMember(memberName, BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.IgnoreCase); // 2. Check that there were members with matching name. if (members == null || members.Length == 0) throw ExceptionHelper.BuildRunTimeException(node, "Property does not exist : '" + memberName + "' "); // 3. Get the first member that matches the memberName. var matchingMember = members[0]; var memberNameCaseIgnorant = matchingMember.Name; var mode = isStatic ? MemberMode.CustObjMethodStatic : MemberMode.CustObjMethodInstance; // 4. Store information about the member. instance, type, membername. var member = new MemberAccess(mode); member.Name = isStatic ? type.Name : varName; member.DataType = type; member.Instance = obj; member.MemberName = matchingMember.Name; // 1. Property. if (matchingMember.MemberType == MemberTypes.Property) member.Property = type.GetProperty(memberNameCaseIgnorant); // 2. Method else if (matchingMember.MemberType == MemberTypes.Method) member.Method = type.GetMethod(matchingMember.Name); else if (matchingMember.MemberType == MemberTypes.Field) member.Field = type.GetField(matchingMember.Name); return member; }
/// <summary> /// Resolve a symbol that is either a module or function. /// </summary> /// <param name="symscope"></param> /// <param name="name"></param> /// <returns></returns> public static MemberAccess ResolveSymbol(ISymbols symscope, string name) { var symbol = symscope.GetSymbol(name); // Case 2: Module. if (symbol.Category == SymbolCategory.Module) { var msym = symbol as SymbolModule; var mem = new MemberAccess(MemberMode.Module); mem.Type = msym.DataType; mem.Scope = msym.Scope; return mem; } // Case 3: Function. if (symbol.Category == SymbolCategory.Func) { var sfunc = symbol as SymbolFunction; var mem = new MemberAccess(MemberMode.FunctionScript); mem.MemberName = name; mem.Type = sfunc.DataType; mem.Expr = sfunc.FuncExpr as Expr; return mem; } return null; }
/// <summary> /// Gets a see MemberAccess object that represents the instance, member name and other information on the member access expression. /// </summary> /// <param name="node">The Ast node associated with the member access operation</param> /// <param name="methods">The collection of registered methods on various types</param> /// <param name="obj">The object on which the member access is being performed.</param> /// <param name="memberName">The name of the member to get.</param> /// <returns></returns> public static MemberAccess GetLangBasicTypeMember(AstNode node, RegisteredMethods methods, LObject obj, string memberName) { var type = obj.Type; // Get the methods implementation LTypeMethods for this basic type // e.g. string, date, time, array , map // e.g. LStringType LDateType, LTimeType, LArrayType, LMapType var typeMethods = methods.Get(type); var memberExists = typeMethods.HasMember(obj, memberName); // 1. Can set non-existing map properties if (type == LTypes.Map && !memberExists) { var nonExistMAccess = new MemberAccess(MemberMode.PropertyMember); nonExistMAccess.Name = type.Name; nonExistMAccess.Instance = obj; nonExistMAccess.MemberName = memberName; nonExistMAccess.Type = type; nonExistMAccess.MemberMissing = true; return nonExistMAccess; } // 2. Check that the member exists. if (!memberExists) throw ExceptionHelper.BuildRunTimeException(node, "Property or Member : " + memberName + " does not exist"); // 3. It's either a Property or method var isProp = typeMethods.HasProperty(obj, memberName); var mode = isProp ? MemberMode.PropertyMember : MemberMode.MethodMember; var maccess = new MemberAccess(mode); maccess.Name = type.Name; maccess.Instance = obj; maccess.MemberName = memberName; maccess.Type = type; return maccess; }
private bool IsMemberCall(MemberAccess maccess) { if (maccess.IsInternalExternalFunctionCall() || (maccess.Mode == MemberMode.MethodMember || maccess.Mode == MemberMode.PropertyMember && maccess.Type != null) || maccess.Mode == MemberMode.CustObjMethodInstance || maccess.Mode == MemberMode.CustObjMethodStatic ) return true; return false; }
/// <summary> /// Execute a member call. /// </summary> /// <param name="ctx">The context of the script</param> /// <param name="memberAccess">Object to hold all the relevant information required for the member call.</param> /// <param name="paramListExpressions">The expressions to resolve as parameters</param> /// <param name="paramList">The list of parameters.</param> /// <returns></returns> public static object CallMemberOnClass(Context ctx, AstNode node, MemberAccess memberAccess, List<Expr> paramListExpressions, List<object> paramList, IAstVisitor visitor) { object result = LObjects.Null; var obj = memberAccess.Instance; var type = memberAccess.DataType; // Case 1: Property access if (memberAccess.Property != null) { var prop = type.GetProperty(memberAccess.MemberName); if (prop != null) result = prop.GetValue(obj, null); } // Case 2: Method call. else if( memberAccess.Method != null) { result = FunctionHelper.MethodCall(ctx, obj, type, memberAccess.Method, paramListExpressions, paramList, true, visitor); } // Case 1: Property access if (memberAccess.Field != null) { result = memberAccess.Field.GetValue(obj); } result = CheckConvert(result); return result; }
/// <summary> /// Calls a property get /// </summary> /// <param name="ctx">The context of the runtime</param> /// <param name="memberAccess">Object to hold all the relevant information required for the member call.</param> /// <param name="paramListExpressions">The collection of parameters as expressions</param> /// <param name="paramList">The collection of parameter values after they have been evaluated</param> /// <returns></returns> public static object CallMemberOnBasicType(Context ctx, AstNode node, MemberAccess memberAccess, List<Expr> paramListExpressions, List<object> paramList, IAstVisitor visitor) { object result = null; // 1. Get methods var methods = ctx.Methods.Get(memberAccess.Type); // 2. Get object on which method/property is being called on. var lobj = (LObject)memberAccess.Instance; // 3. Property ? if (memberAccess.Mode == MemberMode.PropertyMember) { result = methods.GetProperty(lobj, memberAccess.MemberName); } // 4. Method else if (memberAccess.Mode == MemberMode.MethodMember) { object[] args = null; if(paramListExpressions != null && paramListExpressions.Count > 0) { ParamHelper.ResolveNonNamedParameters(paramListExpressions, paramList, visitor); args = paramList.ToArray(); } result = methods.ExecuteMethod(lobj, memberAccess.MemberName, args); } result = CheckConvert(result); return result; }
private MemberAccess GetMemberAccess(Type type, object obj, bool isStatic) { // 1. Get the member name. MemberInfo[] members = null; members = type.GetMember(MemberName, BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.IgnoreCase); MemberInfo result = null; // 2. Validate: Property does not exist ? if (members == null || members.Length == 0) throw BuildRunTimeException("Property does not exist : '" + MemberName + "' "); // 3. Get the first member. result = members[0]; string memberNameCaseIgnorant = result.Name; MemberMode mode = isStatic ? MemberMode.CustObjMethodStatic : MemberMode.CustObjMethodInstance; MemberAccess member = new MemberAccess(mode); member.DataType = type; member.Instance = obj; member.MemberName = MemberName; // Property. if (result.MemberType == MemberTypes.Property) { member.Name = type.Name; member.Property = type.GetProperty(memberNameCaseIgnorant); } // Method else if (result.MemberType == MemberTypes.Method) { string name = (VariableExp.IsNodeType(NodeTypes.SysVariable)) ? ((VariableExpr)VariableExp).Name : null; member.Name = name; member.Method = type.GetMethod(memberNameCaseIgnorant); } return member; }