/// <summary> /// Calls an internal function or external function. /// </summary> /// <param name="ctx">The context of the runtime.</param> /// <param name="fexpr">The function call expression</param> /// <param name="functionName">The name of the function. if not supplied, gets from the fexpr</param> /// <param name="pushCallStack"></param> /// <returns></returns> public static object CallFunction(Context ctx, FunctionCallExpr fexpr, string functionName, bool pushCallStack) { if (string.IsNullOrEmpty(functionName)) { functionName = fexpr.NameExp.ToQualifiedName(); } if (!FunctionHelper.IsInternalOrExternalFunction(ctx, functionName, null)) { throw ExceptionHelper.BuildRunTimeException(fexpr, "Function does not exist : '" + functionName + "'"); } // 1. Push the name of the function on teh call stack if (pushCallStack) { ctx.State.Stack.Push(functionName, fexpr); } // 2. Call the function. object result = null; // Case 1: Custom C# function blog.create blog.* if (ctx.ExternalFunctions.Contains(functionName)) { result = ctx.ExternalFunctions.Call(functionName, fexpr); } // Case 2: Script functions "createUser('john');" else { result = FunctionHelper.CallFunctionInScript(ctx, functionName, fexpr.ParamListExpressions, fexpr.ParamList, true); } // 3. Finnaly pop the call stact. if (pushCallStack) { ctx.State.Stack.Pop(); } result = CheckConvert(result); return(result); }
/// <summary> /// Call a fluent script function from c#. /// </summary> /// <param name="context">The context of the call.</param> /// <param name="expr">The lambda function</param> /// <param name="convertApplicableTypes">Whether or not to convert applicable c# types to fluentscript types, eg. ints and longs to double, List(object) to LArrayType and Dictionary(string, object) to LMapType</param> /// <param name="args"></param> public static object CallFunctionViaCSharpUsingLambda(Context context, FunctionExpr expr, bool convertApplicableTypes, params object[] args) { var argsList = args.ToList <object>(); if (convertApplicableTypes) { LangTypeHelper.ConvertToLangTypeValues(argsList); } var execution = new Execution(); execution.Ctx = context; if (EvalHelper.Ctx == null) { EvalHelper.Ctx = context; } var result = FunctionHelper.CallFunctionInScript(context, execution, expr.Meta.Name, expr, null, argsList, false); return(result); }
/// <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) { 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); } result = CheckConvert(result); return(result); }
/// <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); }