protected internal override YqlCompiledNode CompileNode(YqlCompiler compiler) { if (Items.Count == 0) { ReportError("The list must contain at least one item"); } var compiledItems = compiler.CompileNodes(Items); Type itemType = compiledItems[0].Expression.Type; // Enforce that the other items have the same type for (int i = 0; i < compiledItems.Length; ++i) { var compiledItem = compiledItems[i]; if (compiledItem.Expression.Type != itemType) { ReportError("The list items must all have the same type as the first item: " + itemType.Name); } } // TODO: It would be more efficient to store the array in ExecutionContext // rather than reconstructing it each time the expression is evaluated NewArrayExpression expression = Expression.NewArrayInit(itemType, compiledItems.Select(x => x.Expression).ToArray() ); return(new YqlCompiledNode(this, expression, compiledItems)); }
YqlCompiledNode CompileAndOr(YqlCompiler compiler) { if (Args.Count == 0) { ReportError("The " + Operation + " operation requires at least one argument"); } var compiledArgs = compiler.CompileNodes(Args); Expression expression = compiledArgs[0].Expression; for (int i = 1; i < compiledArgs.Length; ++i) { if (Operation == YqlOperation.And) { expression = Expression.And(expression, compiledArgs[i].Expression); } else { expression = Expression.Or(expression, compiledArgs[i].Expression); } } return(new YqlCompiledNode(this, expression, compiledArgs)); }
protected internal override YqlCompiledNode CompileNode(YqlCompiler compiler) { switch (Operation) { case YqlOperation.GreaterThan: case YqlOperation.GreaterThanOrEqual: case YqlOperation.LessThan: case YqlOperation.LessThanOrEqual: case YqlOperation.Equal: case YqlOperation.NotEqual: return(CompileBinaryOp(compiler)); case YqlOperation.And: case YqlOperation.Or: return(CompileAndOr(compiler)); case YqlOperation.Not: return(CompileUnary(compiler)); case YqlOperation.MyUserId: return(CompileSimpleOperation(compiler)); default: ReportError("Unimplemented operation " + Operation); return(null); } }
public void LoadQuery(YamsterModelQuery query) { RequireNotDisposed(); bool succeeded = false; try { Query = query; CompiledFunc = null; if (query != null) { CompiledFunc = YqlCompiler.Compile(query); } Invalidate(); succeeded = true; } finally { if (!succeeded) { Query = null; CompiledFunc = null; Invalidate(); } } }
protected internal override YqlCompiledNode CompileNode(YqlCompiler compiler) { if (List == null) { throw new ArgumentNullException("List"); } if (ItemToFind == null) { throw new ArgumentNullException("ItemToFind"); } var compiledList = List.CompileNode(compiler); var listType = compiledList.Expression.Type; YqlCompiledNode compiledItemToFind = null; Expression expression = null; if (listType.IsArray) { Type itemType = compiledList.Expression.Type.GetElementType(); compiledItemToFind = compiler.CoerceTo( ItemToFind.CompileNode(compiler), itemType ); expression = Expression.Call( Info_ContainsCallback.MakeGenericMethod(itemType), compiledList.Expression, compiledItemToFind.Expression ); } else if (listType == typeof(YamsterUserSet)) { compiledItemToFind = compiler.CoerceTo( ItemToFind.CompileNode(compiler), typeof(long) ); // list.FindUserById(itemToFind) != null expression = Expression.NotEqual( Expression.Call( compiledList.Expression, YamsterUserSet.Info_FindUserById, compiledItemToFind.Expression ), Expression.Constant(null) ); } else { ReportError("The expression type " + listType.Name + " is not a list"); } return(new YqlCompiledNode(this, expression, new[] { compiledList, compiledItemToFind })); }
protected internal override YqlCompiledNode CompileNode(YqlCompiler compiler) { var propertyInfo = Mapping.GetPropertyInfo(this); Type targetType = propertyInfo.DeclaringType; YqlCompiledNode[] compiledArgs; Expression targetExpression = CompileTargetExpression(compiler, out compiledArgs); Expression expression = Expression.Property(targetExpression, propertyInfo); return(new YqlCompiledNode(this, expression, compiledArgs)); }
internal static Func <YqlExecutionContext, bool> Compile(YamsterModelQuery query) { var compiler = new YqlCompiler(query); var compiledQuery = compiler.CoerceTo(compiler.CompileNode(query.FilterNode), typeof(bool), "Expecting a boolean expression"); var filterExpression = Expression.Lambda <Func <YqlExecutionContext, bool> >( compiledQuery.Expression, compiler.ExecutionContextParameter); var compiledFunc = filterExpression.Compile(); return(compiledFunc); }
protected Expression CompileTargetExpression(YqlCompiler compiler, out YqlCompiledNode[] compiledArgs) { Type targetType = YamsterModel.GetModelClass(this.TargetObjectType); Expression targetExpression; if (TargetObject != null) { var compiledTargetObject = compiler.CompileNode(TargetObject); if (compiledTargetObject.Expression.Type != targetType) { ReportError("The target object is " + compiledTargetObject.Expression.Type.Name + ", which cannot be converted to " + targetType.Name); } targetExpression = compiledTargetObject.Expression; compiledArgs = new[] { compiledTargetObject }; } else { if (compiler.ModelType != TargetObjectType) { ReportError("This expression attempts to retrieve a {0} property from the" + " current context item, which is a {1} object", this.TargetObjectType, compiler.ModelType); } switch (compiler.ModelType) { case YamsterModelType.Thread: targetExpression = Expression.Property(compiler.ExecutionContextParameter, YqlExecutionContext.Info_Thread); break; case YamsterModelType.Message: targetExpression = Expression.Property(compiler.ExecutionContextParameter, YqlExecutionContext.Info_Message); break; default: throw new NotSupportedException(); } compiledArgs = new YqlCompiledNode[0]; } return(targetExpression); }
protected internal override YqlCompiledNode CompileNode(YqlCompiler compiler) { if (SourceString == null) { throw new ArgumentNullException("SourceString"); } YqlCompiledNode sourceStringNode = SourceString.CompileNode(compiler); // Get the body text TextMatcher textMatcher = new TextMatcher(this.searchText, this.WholeWords, this.MatchAllWords); Expression expression = Expression.Call(Expression.Constant(textMatcher), TextMatcher.Info_IsMatch, sourceStringNode.Expression); return(new YqlCompiledNode(this, expression, new[] { sourceStringNode })); }
YqlCompiledNode CompileBinaryOp(YqlCompiler compiler) { if (Args.Count != 2) { ReportError("The " + Operation + " operation requires two arguments"); } var compiledArgs = compiler.CompileNodes(Args); var leftExpression = compiledArgs[0].Expression; var rightExpression = compiledArgs[1].Expression; Expression expression; switch (Operation) { case YqlOperation.GreaterThan: expression = Expression.GreaterThan(leftExpression, rightExpression); break; case YqlOperation.GreaterThanOrEqual: expression = Expression.GreaterThanOrEqual(leftExpression, rightExpression); break; case YqlOperation.LessThan: expression = Expression.LessThan(leftExpression, rightExpression); break; case YqlOperation.LessThanOrEqual: expression = Expression.LessThanOrEqual(leftExpression, rightExpression); break; case YqlOperation.Equal: expression = Expression.Equal(leftExpression, rightExpression); break; case YqlOperation.NotEqual: expression = Expression.NotEqual(leftExpression, rightExpression); break; default: throw new NotImplementedException(); } return(new YqlCompiledNode(this, expression, compiledArgs)); }
YqlCompiledNode CompileSimpleOperation(YqlCompiler compiler) { if (Args.Count != 0) { ReportError("The " + Operation + " operation cannot have any arguments"); } Expression expression; switch (Operation) { case YqlOperation.MyUserId: expression = Expression.Property(compiler.ExecutionContextParameter, YqlExecutionContext.Info_CurrentUserId); break; default: throw new NotImplementedException(); } return(new YqlCompiledNode(this, expression)); }
YqlCompiledNode CompileUnary(YqlCompiler compiler) { if (Args.Count != 1) { ReportError("The " + Operation + " operation requires one argument"); } var compiledArgs = compiler.CompileNodes(Args); var operandExpression = compiledArgs[0].Expression; Expression expression; switch (Operation) { case YqlOperation.Not: expression = Expression.Not(operandExpression); break; default: throw new NotImplementedException(); } return(new YqlCompiledNode(this, expression, compiledArgs)); }
internal protected abstract YqlCompiledNode CompileNode(YqlCompiler compiler);
protected internal override YqlCompiledNode CompileNode(YqlCompiler compiler) { Expression valueExpression = Expression.Constant(Value); return(new YqlCompiledNode(this, valueExpression)); }