API 0.9.5
Foundation/CPPredicate/CPExpression_function.j
Go to the documentation of this file.
00001 /*
00002  * CPExpression_function.j
00003  *
00004  * Created by cacaodev.
00005  * Copyright 2010.
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this library; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00020  */
00021 
00022 
00023 @implementation CPExpression_function : CPExpression
00024 {
00025     CPExpression    _operand;
00026     SEL             _selector;
00027     CPArray         _arguments;
00028     int             _argc;
00029     int             _maxargs;
00030 }
00031 
00032 - (id)initWithSelector:(SEL)aSelector arguments:(CPArray)parameters
00033 {
00034     var target = [CPPredicateUtilities class];
00035     if (![target respondsToSelector:aSelector])
00036         [CPException raise:CPInvalidArgumentException reason:@"Unknown function implementation: " + aSelector];
00037 
00038     var operand = [CPExpression expressionForConstantValue:target];
00039     return [self initWithTarget:operand selector:aSelector arguments:parameters];
00040 }
00041 
00042 - (id)initWithTarget:(CPExpression)operand selector:(SEL)aSelector arguments:(CPArray)parameters
00043 {
00044     return [self initWithTarget:operand selector:aSelector arguments:parameters type:CPFunctionExpressionType];
00045 }
00046 
00047 - (id)initWithTarget:(CPExpression)operand selector:(SEL)aSelector arguments:(CPArray)parameters type:(int)type
00048 {
00049     self = [super initWithExpressionType:type];
00050 
00051     if (self)
00052     {
00053         // Cocoa doc: "This method throws an exception immediately if the selector is unknown"
00054         // but operand's value (the target) may be resolved only at runtime.
00055         _selector = aSelector;
00056         _operand = operand;
00057         _arguments = parameters;
00058         _argc = [parameters count];
00059         _maxargs = [[CPStringFromSelector(_selector) componentsSeparatedByString:@":"] count] - 1;
00060     }
00061     return self;
00062 }
00063 
00064 - (BOOL)isEqual:(id)object
00065 {
00066     if (self == object)
00067         return YES;
00068 
00069     if (object.isa != self.isa || [object expressionType] != [self expressionType] || ![[object _function] isEqualToString:[self _function]] || ![[object operand] isEqual:[self operand]] || ![[object arguments] isEqualToArray:[self arguments]])
00070         return NO;
00071 
00072     return YES;
00073 }
00074 
00075 - (CPString)_function // OBJJ preprocessor does not like function as a method
00076 {
00077     return CPStringFromSelector(_selector);
00078 }
00079 
00080 - (CPString)function
00081 {
00082     return [self _function];
00083 }
00084 
00085 - (CPArray)arguments
00086 {
00087     return _arguments;
00088 }
00089 
00090 - (CPExpression)operand
00091 {
00092     return _operand;
00093 }
00094 
00095 - (id)expressionValueWithObject:(id)object context:(CPDictionary)context
00096 {
00097     var target = [_operand expressionValueWithObject:object context:context],
00098         objj_args = [target, _selector],
00099         i = 0;
00100 
00101     for (; i < _argc; i++)
00102     {
00103         var arg = [_arguments[i] expressionValueWithObject:object context:context];
00104         objj_args.push(arg);
00105     }
00106 
00107     // If we have too much arguments, concatenate remaining args on the last one.
00108     if (_argc > _maxargs)
00109     {
00110         var r = MAX(_maxargs + 1, 2);
00111         objj_args = objj_args.slice(0, r).concat([objj_args.slice(r)]);
00112     }
00113 
00114     return objj_msgSend.apply(this, objj_args);
00115 }
00116 
00117 - (CPString)description
00118 {
00119     var result = "";
00120     if ([_operand isEqual:[CPExpression expressionForConstantValue:[CPPredicateUtilities class]]])
00121         result += CPStringFromSelector(_selector) + "(";
00122     else
00123     {
00124         result += "FUNCTION(";
00125         result += _operand ? [_operand description] + ", ":"";
00126         result += _selector ? CPStringFromSelector(_selector) + ", ":"";
00127     }
00128 
00129     for (var i = 0; i < _argc; i++)
00130         result = result + [_arguments[i] description] + ((i + 1 < _argc) ? ", " : "");
00131 
00132     result += ")";
00133 
00134     return result ;
00135 }
00136 
00137 - (CPExpression)_expressionWithSubstitutionVariables:(CPDictionary)variables
00138 {
00139     var operand = [[self operand] _expressionWithSubstitutionVariables:variables],
00140         args = [CPArray array],
00141         i = 0;
00142 
00143     for (; i < _argc; i++)
00144         [args addObject:[_arguments[i] _expressionWithSubstitutionVariables:variables]];
00145 
00146     return [CPExpression expressionForFunction:operand selectorName:[self _function] arguments:args];
00147 }
00148 
00149 @end
00150 
00151 var CPSelectorNameKey   = @"CPSelectorName",
00152     CPArgumentsKey      = @"CPArguments",
00153     CPOperandKey        = @"CPOperand",
00154     CPExpressionTypeKey = @"CPExpressionType";
00155 
00156 @implementation CPExpression_function (CPCoding)
00157 
00158 - (id)initWithCoder:(CPCoder)coder
00159 {
00160     var type = [coder decodeIntForKey:CPExpressionTypeKey],
00161         operand = [coder decodeObjectForKey:CPOperandKey],
00162         selector = CPSelectorFromString([coder decodeObjectForKey:CPSelectorNameKey]),
00163         parameters = [coder decodeObjectForKey:CPArgumentsKey];
00164 
00165     return [self initWithTarget:operand selector:selector arguments:parameters type:type];
00166 }
00167 
00168 - (void)encodeWithCoder:(CPCoder)coder
00169 {
00170     [coder encodeObject:[self _function] forKey:CPSelectorNameKey];
00171     [coder encodeObject:_arguments forKey:CPArgumentsKey];
00172     [coder encodeObject:_operand forKey:CPOperandKey];
00173     [coder encodeInt:_type forKey:CPExpressionTypeKey];
00174 }
00175 
00176 @end
00177 
00178 // Built-in functions
00179 @implementation CPPredicateUtilities : CPObject
00180 {
00181     id __doxygen__;
00182 }
00183 
00184 + (float)sum:(CPArray)parameters
00185 {
00186     var sum = 0,
00187         count = parameters.length;
00188 
00189     while (count--)
00190         sum += parameters[count];
00191 
00192     return sum;
00193 }
00194 
00195 + (float)count:(CPArray)parameters
00196 {
00197     return [parameters count];
00198 }
00199 
00200 + (float)min:(CPArray)parameters
00201 {
00202     return parameters.sort()[0];
00203 }
00204 
00205 + (float)max:(CPArray)parameters
00206 {
00207     return parameters.sort()[parameters.length - 1];
00208 }
00209 
00210 + (float)average:(CPArray)parameters
00211 {
00212     return [self sum:parameters] / parameters.length;
00213 }
00214 
00215 + (id)first:(CPArray)parameters
00216 {
00217     return parameters[0];
00218 }
00219 
00220 + (id)last:(CPArray)parameters
00221 {
00222     return parameters[parameters.length - 1];
00223 }
00224 
00225 + (id)fromObject:(id)object index:(id)anIndex
00226 {
00227     if ([object isKindOfClass:[CPDictionary class]])
00228         return [object objectForKey:anIndex];
00229     else ([object isKindOfClass:[CPArray class]])
00230         return [object objectAtIndex:anIndex];
00231 
00232     [CPException raise:CPInvalidArgumentException reason:@"object[#] requires a CPDictionary or CPArray"];
00233 }
00234 
00235 + (float)add:(int)n to:(int)m
00236 {
00237     return n + m;
00238 }
00239 
00240 + (float)from:(int)n substract:(int)m
00241 {
00242     return n - m;
00243 }
00244 
00245 + (float)multiply:(float)n by:(int)m
00246 {
00247     return n * m;
00248 }
00249 
00250 + (float)divide:(float)n by:(float)m
00251 {
00252     return n / m;
00253 }
00254 
00255 + (float)sqrt:(float)n
00256 {
00257     return SQRT(n);
00258 }
00259 
00260 + (float)raise:(float)num to:(int)power
00261 {
00262     return POW(num, power);
00263 }
00264 
00265 + (float)abs:(float)num
00266 {
00267     return ABS(num);
00268 }
00269 
00270 + (CPDate)now:(id)_
00271 {
00272     return [CPDate date];
00273 }
00274 
00275 + (float)ln:(float)num
00276 {
00277     return LN10(num);
00278 }
00279 
00280 + (float)exp:(float)num
00281 {
00282     return EXP(num);
00283 }
00284 
00285 + (float)ceiling:(float)num
00286 {
00287     return CEIL(num);
00288 }
00289 
00290 + (int)random:(int)num
00291 {
00292     return ROUND(RAND() * num);
00293 }
00294 
00295 + (int)modulus:(int)n by:(int)m
00296 {
00297     return n % m;
00298 }
00299 
00300 + (float)chs:(int)num
00301 {
00302     return -num;
00303 }
00304 
00305 @end
 All Classes Files Functions Variables Defines