/// <summary> /// Visit the anyof expression. /// </summary> /// <param name="expr">AnyOf expression.</param> /// <returns></returns> public object VisitAnyOf(AnyOfExpr expr) { var result = false; var leftExpr = expr.CompareExpr; var leftResult = leftExpr.Evaluate(this) as LObject; if (expr.ParamListExpressions == null || expr.ParamListExpressions.Count == 0) { return(new LBool(result)); } // Resolve the parameters. ParamHelper.ResolveNonNamedParameters(expr.ParamListExpressions, expr.ParamList, this); foreach (var rvalue in expr.ParamList) { var rightResult = rvalue as LObject; var compareResult = EvalHelper.Compare(expr, Operator.EqualEqual, leftResult, rightResult) as LObject; if (compareResult != null && compareResult.Type == LTypes.Bool && ((LBool)compareResult).Value == true) { result = true; break; } } return(new LBool(result)); }
/// <summary> /// Evaluate object[index] /// </summary> /// <returns></returns> public object VisitIndex(IndexExpr expr) { var ndxVal = expr.IndexExp.Evaluate(this); var listObject = expr.VarExp.Evaluate(this); // Check for empty objects. ExceptionHelper.NotNull(expr, listObject, "indexing"); ExceptionHelper.NotNull(expr, ndxVal, "indexing"); var lobj = (LObject)listObject; // CASE 1. Access // e.g. Array: users[0] // e.g. Map: users['total'] if (!expr.IsAssignment) { var result = EvalHelper.AccessIndex(Ctx.Methods, expr, lobj, (LObject)ndxVal); return(result); } // CASE 2. Assignment // e.g. Array: users[0] = 'john' // e.g. Map: users['total'] = 200 // NOTE: In this case of assignment, return back a MemberAccess object descripting what is assign var indexAccess = new IndexAccess(); indexAccess.Instance = lobj; indexAccess.MemberName = (LObject)ndxVal; return(indexAccess); }
/// <summary> /// Execute each expression. /// </summary> /// <returns></returns> public object VisitFor(ForExpr expr) { expr.Start.Evaluate(this); expr.DoContinueRunning = true; expr.DoBreakLoop = false; expr.DoContinueLoop = false; var result = expr.Condition.Evaluate(this) as LObject; expr.DoContinueRunning = EvalHelper.IsTrue(result); while (expr.DoContinueRunning) { if (expr.Statements != null && expr.Statements.Count > 0) { foreach (var stmt in expr.Statements) { stmt.Evaluate(this); this.Ctx.Limits.CheckLoop(expr); // If Break statment executed. if (expr.DoBreakLoop) { expr.DoContinueRunning = false; break; } // Continue statement. else if (expr.DoContinueLoop) { break; } } } else { break; } // Break loop here. if (expr.DoContinueRunning == false) { break; } expr.Increment.Evaluate(this); result = expr.Condition.Evaluate(this) as LObject; expr.DoContinueRunning = EvalHelper.IsTrue(result); } return(LObjects.Null); }
/// <summary> /// Evaluate > >= != == less less than /// </summary> /// <returns></returns> public object VisitCompare(CompareExpr expr) { var node = expr; var op = expr.Op; // TODO: This should be here ( find a better solution ) // e.g. allow expression to support comparable ?? if (expr.Right.Nodetype == NodeTypes.SysAnyOf) { var anyOf = ((AnyOfExpr)expr.Right); anyOf.CompareExpr = expr.Left; return(this.VisitAnyOf(anyOf)); } var left = (LObject)expr.Left.Evaluate(this); var right = (LObject)expr.Right.Evaluate(this); return(EvalHelper.Compare(node, op, left, right)); }
/// <summary> /// Execute /// </summary> public object VisitIf(IfExpr expr) { // Case 1: If is true var result = expr.Condition.Evaluate(this) as LObject; bool execIf = EvalHelper.IsTrue(result); object returnVal = LObjects.Null; if (execIf) { if (expr.Statements != null && expr.Statements.Count > 0) { foreach (var stmt in expr.Statements) { returnVal = stmt.Evaluate(this); } } } // Case 2: Else available to execute else if (expr.Else != null) { returnVal = expr.Else.Evaluate(this); } return(returnVal); }
/// <summary> /// Visita a compare expression with the values evaluated. /// </summary> /// <param name="node"></param> /// <param name="op"></param> /// <param name="left"></param> /// <param name="right"></param> /// <returns></returns> public static object Compare(AstNode node, Operator op, LObject left, LObject right) { object result = null; // Both double if (left.Type == LTypes.Number && right.Type == LTypes.Number) { result = EvalHelper.CompareNumbers(node, (LNumber)left, (LNumber)right, op); } // Both strings else if (left.Type == LTypes.String && right.Type == LTypes.String) { result = EvalHelper.CompareStrings(node, (LString)left, (LString)right, op); } // Both bools else if (left.Type == LTypes.Bool && right.Type == LTypes.Bool) { result = EvalHelper.CompareBools(node, (LBool)left, (LBool)right, op); } // Both dates else if (left.Type == LTypes.Date && right.Type == LTypes.Date) { result = EvalHelper.CompareDates(node, (LDate)left, (LDate)right, op); } // Both Timespans else if (left.Type == LTypes.Time && right.Type == LTypes.Time) { result = EvalHelper.CompareTimes(node, (LTime)left, (LTime)right, op); } // 1 or both null else if (left == LObjects.Null || right == LObjects.Null) { result = EvalHelper.CompareNull(left, right, op); } // Day of week ? else if (left.Type == LTypes.DayOfWeek || right.Type == LTypes.DayOfWeek) { result = EvalHelper.CompareDays(node, left, right, op); } // Date and time ? else if ((left.Type == LTypes.Date && right.Type == LTypes.Time) || (left.Type == LTypes.Time && right.Type == LTypes.Date)) { result = EvalHelper.CompareDayDifference(node, left, right, op); } // Units //else if (left.Type == LTypes.Unit || right.Type == LTypes.Unit) else if (left.Type.Name == "LUnit" || right.Type.Name == "LUnit") { result = EvalHelper.CompareUnits(node, (LUnit)((LClass)left).Value, (LUnit)((LClass)right).Value, op); } return(result); }
/// <summary> /// Evaluate * / + - % /// </summary> /// <returns></returns> public object VisitBinary(BinaryExpr expr) { // Validate object result = 0; var node = expr; var op = expr.Op; var left = (LObject)expr.Left.Evaluate(this); var right = (LObject)expr.Right.Evaluate(this); // Case 1: Both numbers if (IsTypeMatch(LTypes.Number, left, right)) { result = EvalHelper.CalcNumbers(node, (LNumber)left, (LNumber)right, op); } // Case 2: Both times else if (IsTypeMatch(LTypes.Time, left, right)) { result = EvalHelper.CalcTimes(node, (LTime)left, (LTime)right, op); } // Case 3: Both dates else if (IsTypeMatch(LTypes.Date, left, right)) { result = EvalHelper.CalcDates(node, (LDate)left, (LDate)right, op); } // Case 4: Both strings. else if (IsTypeMatch(LTypes.String, left, right)) { var strleft = ((LString)left).Value; var strright = ((LString)right).Value; // Check string limit. this.Ctx.Limits.CheckStringLength(node, strleft, strright); result = new LString(strleft + strright); } // MIXED TYPES // TODO: Needs to be improved with new code for types. // Case 5 : Double and Bool else if (left.Type == LTypes.Number && right.Type == LTypes.Bool) { var r = ((LBool)right).Value; var rval = r ? 1 : 0; result = EvalHelper.CalcNumbers(node, (LNumber)left, new LNumber(rval), op); } // Bool Double else if (left.Type == LTypes.Bool && right.Type == LTypes.Number) { var l = ((LBool)left).Value; var lval = l ? 1 : 0; result = EvalHelper.CalcNumbers(node, new LNumber(lval), (LNumber)right, op); } // Append as strings. else if (left.Type == LTypes.String && right.Type == LTypes.Bool) { var st1 = ((LString)left).Value + ((LBool)right).Value.ToString().ToLower(); result = new LString(st1); } // Append as strings. else if (left.Type == LTypes.Bool && right.Type == LTypes.String) { var st2 = ((LBool)left).Value.ToString().ToLower() + ((LString)right).Value; result = new LString(st2); } // TODO: Need to handle LUnit and LVersion better //else if (left.Type == LTypes.Unit && right.Type == LTypes.Unit) else if (left.Type.TypeVal == TypeConstants.Unit && right.Type.TypeVal == TypeConstants.Unit) { result = EvalHelper.CalcUnits(node, (LUnit)((LClass)left).Value, (LUnit)((LClass)right).Value, op, this.Ctx.Units); } else { // Check for null var lStringVal = ""; var rStringVal = ""; if (left != LObjects.Null) { lStringVal = left.GetValue().ToString(); } if (right != LObjects.Null) { rStringVal = right.GetValue().ToString(); } var st3 = lStringVal + rStringVal; result = new LString(st3); } return(result); }
/// <summary> /// Evaluate /// </summary> /// <returns></returns> public object VisitNegate(NegateExpr expr) { return(EvalHelper.Negate(expr, this)); }