/// <summary> /// Calls the custom function. /// </summary> /// <param name="name">Name of the function</param> /// <param name="exp"></param> /// <returns></returns> public object Call(string name, FunctionCallExpr exp, IAstVisitor visitor) { var objectName = name; var method = string.Empty; Func<string, string, FunctionCallExpr, object> callback = null; // Contains callback for full function name ? e.g. CreateUser if (_customCallbacks.ContainsKey(name)) callback = _customCallbacks[name]; // Contains callback that handles multiple methods on a "object". // e.g. Blog.Create, Blog.Delete etc. if (name.Contains(".")) { var ndxDot = name.IndexOf("."); objectName = name.Substring(0, ndxDot); method = name.Substring(ndxDot + 1); if (_customCallbacks.ContainsKey(objectName + ".*")) callback = _customCallbacks[objectName + ".*"]; } if (callback == null) return LObjects.Null; // 1. Resolve parameter froms expressions into Lang values. ParamHelper.ResolveParametersToHostLangValues(exp.ParamListExpressions, exp.ParamList, visitor); object result = callback(objectName, method, exp); return result; }
/// <summary> /// Prints to the console. /// </summary> /// /// <param name="settings">Settings for interpreter</param> /// <param name="exp">The functiona call expression</param> /// <param name="printline">Whether to print with line or no line</param> public static string Print(LangSettings settings, FunctionCallExpr exp, bool printline) { if (!settings.EnablePrinting) return string.Empty; string message = BuildMessage(exp.ParamList); if (printline) Console.WriteLine(message); else Console.Write(message); return message; }
/// <summary> /// Logs severity to console. /// </summary> /// <param name="settings">Settings for interpreter</param> /// <param name="exp">The functiona call expression</param> public static string Log(LangSettings settings, FunctionCallExpr exp) { if (!settings.EnableLogging) return string.Empty; var funcname = exp.ToQualifiedName(); var severity =funcname.Substring(funcname.IndexOf(".") + 1); var message = BuildMessage(exp.ParamList); Console.WriteLine(severity.ToUpper() + " : " + message); return message; }
/// <summary> /// Calls the custom function. /// </summary> /// <param name="name">Name of the function</param> /// <param name="exp"></param> /// <returns></returns> public object Call(string name, FunctionCallExpr exp) { var callback = GetByName(name); // 1. Resolve parameter froms expressions into Lang values. ParamHelper.ResolveParametersToHostLangValues(exp.ParamListExpressions, exp.ParamList); object result = callback(exp); return result; }
/// <summary> /// Push the function expression on the call stack /// </summary> /// <param name="qualifiedName">Name of function call</param> /// <param name="exp">Function Call expression</param> public bool Push(string qualifiedName, FunctionCallExpr exp) { _stack.Add(new Tuple<string, FunctionCallExpr>(qualifiedName, exp)); _lastIndex++; if (_limitCheck != null) _limitCheck(exp, _lastIndex); return true; }
/// <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, IAstVisitor visitor) { if(string.IsNullOrEmpty(functionName)) functionName = fexpr.NameExp.ToQualifiedName(); // 1. Check if script func or extern func. var isScriptFunc = fexpr.SymScope.IsFunction(functionName); var isExternFunc = ctx.ExternalFunctions.Contains(functionName); // 2. If neither, this is an error scenario. if (!isScriptFunc && !isExternFunc) throw ExceptionHelper.BuildRunTimeException(fexpr, "Function does not exist : '" + functionName + "'"); // 3. Push the name of the function on teh call stack if(pushCallStack) ctx.State.Stack.Push(functionName, fexpr); // 4. Call the function. object result = null; // Case 1: Custom C# function blog.create blog.* if (isExternFunc) result = ctx.ExternalFunctions.Call(functionName, fexpr, visitor); // Case 2: Script functions "createUser('john');" else { var sym = fexpr.SymScope.GetSymbol(functionName) as SymbolFunction; var func = sym.FuncExpr as FunctionExpr; result = FunctionHelper.CallFunctionInScript(ctx, func, functionName, fexpr.ParamListExpressions, fexpr.ParamList, true, visitor); } // 3. Finnaly pop the call stact. if(pushCallStack) ctx.State.Stack.Pop(); result = CheckConvert(result); return result; }
/// <summary> /// Visits the function call expression tree /// </summary> /// <param name="exp"></param> public object VisitFunctionCall(FunctionCallExpr exp) { _callBackOnNodeStart(exp); foreach (var paramExp in exp.ParamListExpressions) _callBackOnNodeStart(paramExp); _callBackOnNodeEnd(exp); return null; }
/// <summary> /// Parses the fluent function call. /// </summary> /// <returns></returns> public override Expr Parse() { // 1. Is it a function call? var fnameToken = _tokenIt.NextToken; _tokenIt.Advance(_result.TokenCount); string remainderOfFuncName = string.Empty; var parts = new List<Expr>(); TokenData firstPart = null; // NOTES: // Given: function "Find user by" * // And: called via Find use by name role // wildcard part 1: name // wildcard part 2: role // full wildcard: "name role" var partsToken = _tokenIt.NextToken; // 1. Capture all the remaining parts of the wild card. while (_tokenIt.NextToken.Token.Kind == TokenKind.Ident) { string part = _tokenIt.NextToken.Token.Text; // a. Store the token of the first wildcard part if(firstPart == null) firstPart = _tokenIt.NextToken; // b. Build up the full name from all wildcards remainderOfFuncName += " " + part; // c. Create a constant expr from the wildcard // as it will be part of an array of strings passed to function var partExp = Exprs.Const(new LString(part), _tokenIt.NextToken); parts.Add(partExp); // d. Move to the next token for another possible wildcard. _tokenIt.Advance(); // e. Check for end of statement. if (_tokenIt.IsEndOfStmtOrBlock()) break; } var exp = new FunctionCallExpr(); exp.ParamListExpressions = new List<Expr>(); exp.ParamList = new List<object>(); remainderOfFuncName = remainderOfFuncName.Trim(); var fullWildCard = Exprs.Const(new LString(string.Empty), fnameToken) as ConstantExpr; // 2. Create a constant expr representing the full wildcard if(!string.IsNullOrEmpty(remainderOfFuncName)) { fullWildCard.Value = remainderOfFuncName; _parser.SetupContext(fullWildCard, firstPart); } var token = _tokenIt.NextToken.Token; // CASE 1: Parse parameters with parenthesis "(" if (token == Tokens.LeftParenthesis) { _parser.ParseParameters(exp, true, false, false); } // CASE 2: Parse parameters with ":" until newline. else if (token == Tokens.Colon) { _tokenIt.Advance(); _parser.ParseParameters(exp, false, false, true); } exp.NameExp = Exprs.Ident(_result.Name, fnameToken); // Have to restructure the arguments. // 1. const expr , fullwildcard, "name role" // 2. list<constexpr>, wildcard parts, ["name", "role"] // 3. list<expr>, args, "kishore", "admin" var args = new List<Expr>(); args.Add(fullWildCard); args.Add(Exprs.Array(parts, partsToken)); args.Add(Exprs.Array(exp.ParamListExpressions, fnameToken)); // Finally reset the parameters expr on the function call. exp.ParamListExpressions = args; return exp; }
/// <summary> /// Checks function call expressions for correct number of parameters. /// </summary> /// <param name="semActs">The semantic analyser</param> /// <param name="exp">The functioncallexpression</param> private SemanticCheckResult CheckFunctionCall(SemActs semActs, FunctionCallExpr exp) { var functionName = exp.ToQualifiedName(); var exists = exp.SymScope.IsFunction(functionName); // 1. Function does not exist. if (!exists) { return AddErrorCode(ErrorCodes.Func1000, exp, functionName); } var sym = exp.SymScope.GetSymbol(functionName) as SymbolFunction; var func = sym.FuncExpr as FunctionExpr; // 5. Check that named parameters exist. foreach(var argExpr in exp.ParamListExpressions) { if(argExpr.IsNodeType(NodeTypes.SysNamedParameter)) { var argName = ((NamedParamExpr) argExpr).Name; if (!func.Meta.ArgumentsLookup.ContainsKey(argName)) AddErrorCode(ErrorCodes.Func1002, exp, argName); } } return SemanticCheckResult.Valid; }
/// <summary> /// run step 123. /// </summary> /// <returns></returns> public override Expr Parse() { _tokenIt.Expect(Tokens.Run); // run function 'name'; // run function touser(); if (_tokenIt.NextToken.Token == Tokens.Function) _tokenIt.Advance(); // 'username' if (!(_tokenIt.NextToken.Token.IsLiteralAny() || _tokenIt.NextToken.Token.Kind == TokenKind.Ident)) _tokenIt.BuildSyntaxExpectedException("identifier or string"); var name = _tokenIt.NextToken.Token.Text; // Case 1: run 'step1'; // Case 2: run step1; var next = _tokenIt.Peek(); if (next.Token != Tokens.LeftParenthesis && next.Token != Tokens.Dot) { var funcExp = new FunctionCallExpr(); funcExp.NameExp = _parser.ToIdentExpr(name, null); _parser.State.FunctionCall++; //Ctx.Limits.CheckParserFuncCallNested(_tokenIt.NextToken, _parser.State.FunctionCall); _parser.State.FunctionCall--; // Move past this plugin _tokenIt.Advance(); return funcExp; } // Case 3: run step1(); Expr exp = _parser.ParseIdExpression(name); return exp; }
/// <summary> /// Calls the custom function. /// </summary> /// <param name="exp"></param> /// <returns></returns> public object Call(FunctionCallExpr exp) { return CallByName(exp.ToQualifiedName(), exp.ParamListExpressions, exp.ParamList, true); }
/// <summary> /// Evauate and run the function /// </summary> /// <returns></returns> public object VisitFunctionCall(FunctionCallExpr expr) { object result = null; // CASE 1: Exp is variable -> internal/external script. "getuser()". if (expr.NameExp.IsNodeType(NodeTypes.SysVariable)) { return FunctionHelper.CallFunction(this.Ctx, expr, null, true, this); } // At this point, is a method call on an object. var member = expr.NameExp.Evaluate(this); result = member; var isMemberAccessType = member is MemberAccess; if (!isMemberAccessType) return result; var callStackName = expr.NameExp.ToQualifiedName(); var maccess = member as MemberAccess; if (!IsMemberCall(maccess)) return result; this.Ctx.State.Stack.Push(callStackName, expr); // CASE 2: Module.Function if (maccess.Mode == MemberMode.FunctionScript && maccess.Expr != null) { var fexpr = maccess.Expr as FunctionExpr; result = FunctionHelper.CallFunctionInScript(this.Ctx, fexpr, fexpr.Meta.Name, expr.ParamListExpressions, expr.ParamList, true, this); } // CASE 3: object "." method call from script is a external/internal function e.g log.error -> external c# callback. else if (maccess.IsInternalExternalFunctionCall()) { result = FunctionHelper.CallFunction(Ctx, expr, maccess.FullMemberName, false, this); } // CASE 4: Method call / Property on Language types else if (maccess.Type != null) { result = FunctionHelper.CallMemberOnBasicType(this.Ctx, expr, maccess, expr.ParamListExpressions, expr.ParamList, this); } // CASE 5: Member call via "." : either static or instance method call. e.g. Person.Create() or instance1.FullName() e.g. else if (maccess.Mode == MemberMode.CustObjMethodStatic || maccess.Mode == MemberMode.CustObjMethodInstance) { result = FunctionHelper.CallMemberOnClass(this.Ctx, expr, maccess, expr.ParamListExpressions, expr.ParamList, this); } // Pop the function name off the call stack. this.Ctx.State.Stack.Pop(); return result; }
private object RunCompilerMethod(string objectName, string method, LangSettings settings, FunctionCallExpr ex) { var metaCompiler = new MetaCompiler(); metaCompiler.Ctx = ex.Ctx; if(method == "ToConstDate") { } else if(method == "ToConstTime") { } else if(method == "ToConstDateTimeToken") { var dateToken = ex.ParamList[0] as TokenData; var timeToken = ex.ParamList[1] as TokenData; return metaCompiler.ToConstDateTimeToken(dateToken, timeToken); } else if (method == "ToConstDay") { var token = ex.ParamList[0] as TokenData; var day = Convert.ToInt32(ex.ParamList[1]); return metaCompiler.ToConstDay(day, token); } return LObjects.Null; }
/// <summary> /// Creates a function call expression. /// </summary> /// <param name="nameExpr"></param> /// <param name="parameters"></param> /// <param name="token"></param> /// <returns></returns> public static Expr FunctionCall(Expr nameExpr, List<Expr> parameters, TokenData token) { var funcExp = new FunctionCallExpr(); funcExp.NameExp = nameExpr; funcExp.ParamListExpressions = parameters == null ? new List<Expr>() : parameters; funcExp.ParamList = new List<object>(); SetupContext(funcExp, token); return funcExp; }
/// <summary> /// Creates a function call expression. /// </summary> /// <param name="nameExpr"></param> /// <param name="parameters"></param> /// <param name="token"></param> /// <returns></returns> public Expr ToFunctionCallExpr(Expr nameExpr, List<Expr> parameters, TokenData token) { var funcExp = new FunctionCallExpr(); funcExp.NameExp = nameExpr; funcExp.ParamMap = new Dictionary<string, object>(); this.SetupContext(funcExp, token); return funcExp; }
/// <summary> /// Sorts expression /// </summary> /// <returns></returns> public override Expr Parse(object context) { var constExp = context as ConstantExpr; var c = _tokenIt.NextToken; var t = _tokenIt.Advance(); _parser.SetupContext(constExp, c); // Get the function symbol. var fce = new FunctionCallExpr(); fce.NameExp = _parser.ToIdentExpr(t.Token.Text, t); fce.ParamListExpressions.Add(constExp); // Move the postfix token. _tokenIt.Advance(); return fce; }