mirror of
https://github.com/cappuccino/cappuccino.git
synced 2026-08-25 04:57:03 +00:00
374 lines
9.7 KiB
Plaintext
374 lines
9.7 KiB
Plaintext
|
|
@import "CPExpression.j"
|
|
@import <Foundation/CPString.j>
|
|
@import <Foundation/CPArray.j>
|
|
@import <Foundation/CPDictionary.j>
|
|
|
|
@implementation CPExpression_function : CPExpression
|
|
{
|
|
CPExpression _operand;
|
|
SEL _selector;
|
|
CPArray _arguments;
|
|
int _argc;
|
|
}
|
|
|
|
- (id)initWithSelector:(SEL)aselector arguments:(CPArray)parameters
|
|
{
|
|
[super initWithExpressionType:CPFunctionExpressionType];
|
|
|
|
if (![self respondsToSelector:aselector])
|
|
[CPException raise: CPInvalidArgumentException reason:@"Unknown function implementation: " + aselector];
|
|
|
|
_selector = aselector;
|
|
_operand = nil;
|
|
_arguments = parameters;
|
|
_argc = [parameters count];
|
|
|
|
return self;
|
|
}
|
|
|
|
- (id)initWithTarget:(CPExpression)targetExpression selector:(SEL)aselector arguments:(CPArray)parameters
|
|
{
|
|
[super initWithExpressionType:CPFunctionExpressionType];
|
|
|
|
var target = [targetExpression expressionValueWithObject:object context:context];
|
|
if (![target respondsToSelector:aselector])
|
|
[CPException raise: CPInvalidArgumentException reason:@"Unknown function implementation: " + aselector];
|
|
|
|
_selector = aselector;
|
|
_operand = targetExpression;
|
|
_arguments = parameters;
|
|
_argc = [parameters count];
|
|
|
|
return self;
|
|
}
|
|
|
|
- (id)initWithCoder:(CPCoder)coder
|
|
{
|
|
var selector = CPSelectorFromString([coder decodeObjectForKey:@"CPExpressionFunctionName"]);
|
|
var arguments = [coder decodeObjectForKey:@"CPExpressionFunctionArguments"];
|
|
|
|
return [self initWithSelector:selector arguments:arguments];
|
|
}
|
|
|
|
- (void)encodeWithCoder:(CPCoder)coder
|
|
{
|
|
[coder encodeObject:[self _function] forKey:@"CPExpressionFunctionName"];
|
|
[coder encodeObject:_arguments forKey:@"CPExpressionArguments"];
|
|
}
|
|
|
|
- (BOOL)isEqual:(id)object
|
|
{
|
|
if (self == object)
|
|
return YES;
|
|
|
|
if (object.isa != self.isa || [object expressionType] != [self expressionType] || ![[object _function] isEqualToString:[self _function]] || ![[object operand] isEqual:[self operand]] || ![[object arguments] isEqualToArray:[self arguments]])
|
|
return NO;
|
|
|
|
return YES;
|
|
}
|
|
|
|
- (CPString)_function // OBJJ preprocessor does not like function as a method
|
|
{
|
|
return CPStringFromSelector(_selector);
|
|
}
|
|
|
|
- (CPString)function
|
|
{
|
|
return [self _function];
|
|
}
|
|
|
|
- (CPArray)arguments
|
|
{
|
|
return _arguments;
|
|
}
|
|
|
|
- (CPExpression)operand
|
|
{
|
|
return _operand;
|
|
}
|
|
|
|
- (id)expressionValueWithObject:(id)object context:(CPDictionary)context
|
|
{
|
|
var eval_args = [CPArray array],
|
|
i;
|
|
|
|
for (i = 0; i < _argc; i++)
|
|
{
|
|
var arg = [[_arguments objectAtIndex:i] expressionValueWithObject:object context:context];
|
|
if (arg != nil)
|
|
[eval_args addObject:arg];
|
|
}
|
|
|
|
var target = (_operand == nil) ? self : [_operand expressionValueWithObject:object context:context];
|
|
return [target performSelector:_selector withObject:eval_args];
|
|
}
|
|
|
|
- (CPString)description
|
|
{
|
|
var result = [CPString stringWithFormat:@"%@ %s(", [_operand description], [self _function]],
|
|
i;
|
|
|
|
for (i = 0; i < _argc; i++)
|
|
result = result + [_arguments objectAtIndex:i] + (i+1<_argc) ? ", " : "";
|
|
|
|
result = result + ")";
|
|
|
|
return result ;
|
|
}
|
|
|
|
|
|
- (CPExpression)_expressionWithSubstitutionVariables:(CPDictionary)variables
|
|
{
|
|
var array = [CPArray array],
|
|
i;
|
|
|
|
for (i = 0; i < _argc; i++)
|
|
[array addObject:[[_arguments objectAtIndex:i] _expressionWithSubstitutionVariables:variables]];
|
|
|
|
return [CPExpression expressionForFunction:[self operand] selectorName:[self _function] arguments:array];
|
|
}
|
|
|
|
- (CPNumber)sum:(CPArray)parameters
|
|
{
|
|
if (_argc < 1)
|
|
[CPException raise:CPInvalidArgumentException reason:"Invalid number of parameters"];
|
|
|
|
var i,
|
|
sum = 0.0;
|
|
|
|
for (i = 0; i < _argc; i++)
|
|
sum += [[parameters objectAtIndex:i] doubleValue];
|
|
|
|
return [CPNumber numberWithDouble: sum];
|
|
}
|
|
|
|
- (CPNumber)count:(CPArray)parameters
|
|
{
|
|
if (_argc < 1)
|
|
[CPException raise:CPInvalidArgumentException reason:"Invalid number of parameters"];
|
|
|
|
return [CPNumber numberWithUnsignedInt: [[parameters objectAtIndex:0] count]];
|
|
}
|
|
|
|
- (CPNumber)min:(CPArray)parameters
|
|
{
|
|
if (_argc < 1)
|
|
[CPException raise:CPInvalidArgumentException reason:"Invalid number of parameters"];
|
|
|
|
return MIN([parameters objectAtIndex:0],[parameters objectAtIndex:1]);
|
|
}
|
|
|
|
- (CPNumber)max:(CPArray)parameters
|
|
{
|
|
if (_argc < 1)
|
|
[CPException raise:CPInvalidArgumentException reason:"Invalid number of parameters"];
|
|
|
|
return MAX([parameters objectAtIndex:0],[parameters objectAtIndex:1]);
|
|
}
|
|
|
|
- (CPNumber)average:(CPArray)parameters
|
|
{
|
|
if (_argc < 1)
|
|
[CPException raise:CPInvalidArgumentException reason:"Invalid number of parameters"];
|
|
|
|
var i,
|
|
sum = 0.0;
|
|
|
|
for (i = 0; i < _argc; i++)
|
|
sum += [[parameters objectAtIndex:i] doubleValue];
|
|
|
|
return [CPNumber numberWithDouble: sum / _argc];
|
|
}
|
|
|
|
- (CPNumber)add:to:(CPArray)parameters
|
|
{
|
|
if (_argc != 2)
|
|
[CPException raise:CPInvalidArgumentException reason:"Invalid number of parameters"];
|
|
|
|
var left = [parameters objectAtIndex:0],
|
|
right = [parameters objectAtIndex:1];
|
|
|
|
return [CPNumber numberWithDouble: [left doubleValue] + [right doubleValue]];
|
|
}
|
|
|
|
- (CPNumber)from:subtract:(CPArray)parameters
|
|
{
|
|
if (_argc != 2)
|
|
[CPException raise:CPInvalidArgumentException reason:"Invalid number of parameters"];
|
|
|
|
var left = [parameters objectAtIndex:0],
|
|
right = [parameters objectAtIndex:1];
|
|
|
|
return [CPNumber numberWithDouble: [left doubleValue] - [right doubleValue]];
|
|
}
|
|
|
|
- (CPNumber)multiply:by:(CPArray)parameters
|
|
{
|
|
if (_argc != 2)
|
|
[CPException raise:CPInvalidArgumentException reason:"Invalid number of parameters"];
|
|
|
|
var left = [parameters objectAtIndex:0],
|
|
right = [parameters objectAtIndex:1];
|
|
|
|
return [CPNumber numberWithDouble: [left doubleValue] * [right doubleValue]];
|
|
}
|
|
|
|
- (CPNumber)divide:by:(CPArray)parameters
|
|
{
|
|
if (_argc != 2)
|
|
[CPException raise:CPInvalidArgumentException reason:"Invalid number of parameters"];
|
|
|
|
var left = [parameters objectAtIndex:0],
|
|
right = [parameters objectAtIndex:1];
|
|
|
|
return [CPNumber numberWithDouble: [left doubleValue] / [right doubleValue]];
|
|
}
|
|
|
|
- (CPNumber)sqrt:(CPArray)parameters
|
|
{
|
|
if (_argc != 1)
|
|
[CPException raise:CPInvalidArgumentException reason:"Invalid number of parameters"];
|
|
|
|
var num = [[parameters objectAtIndex:0] doubleValue];
|
|
|
|
return [CPNumber numberWithDouble: SQRT(num)];
|
|
}
|
|
|
|
- (CPNumber)raise:to:(CPArray)parameters
|
|
{
|
|
if (_argc < 2)
|
|
[CPException raise:CPInvalidArgumentException reason:"Invalid number of parameters"];
|
|
|
|
var num = [[parameters objectAtIndex:0] doubleValue],
|
|
power = [[parameters objectAtIndex:1] doubleValue];
|
|
|
|
return [CPNumber numberWithDouble: POW(num,power)];
|
|
}
|
|
|
|
- (CPNumber)abs:(CPArray)parameters
|
|
{
|
|
if (_argc != 1)
|
|
[CPException raise:CPInvalidArgumentException reason:"Invalid number of parameters"];
|
|
|
|
var num = [[parameters objectAtIndex:0] doubleValue];
|
|
|
|
return [CPNumber numberWithDouble:ABS(num)];
|
|
}
|
|
|
|
- (CPDate)now
|
|
{
|
|
return [CPDate date];
|
|
}
|
|
|
|
- (CPNumber)ln:(CPArray)parameters
|
|
{
|
|
if (_argc != 1)
|
|
[CPException raise:CPInvalidArgumentException reason:"Invalid number of parameters"];
|
|
|
|
var num = [[parameters objectAtIndex:0] doubleValue];
|
|
|
|
return [CPNumber numberWithDouble:Math.log(num)];
|
|
}
|
|
|
|
- (CPNumber)exp:(CPArray)parameters
|
|
{
|
|
if (_argc != 1)
|
|
[CPException raise:CPInvalidArgumentException reason:"Invalid number of parameters"];
|
|
|
|
var num = [[parameters objectAtIndex:0] doubleValue];
|
|
|
|
return [CPNumber numberWithDouble:EXP(num)];
|
|
}
|
|
|
|
- (CPNumber)ceiling:(CPArray)parameters
|
|
{
|
|
if (_argc != 1)
|
|
[CPException raise:CPInvalidArgumentException reason:"Invalid number of parameters"];
|
|
|
|
var num = [[parameters objectAtIndex:0] doubleValue];
|
|
|
|
return [CPNumber numberWithDouble:CEIL(num)];
|
|
}
|
|
|
|
- (CPNumber)random
|
|
{
|
|
return [CPNumber numberWithDouble:RAND()];
|
|
}
|
|
|
|
- (CPNumber)modulus:by:(CPArray)parameters
|
|
{
|
|
if (_argc != 2)
|
|
[CPException raise:CPInvalidArgumentException reason:"Invalid number of parameters"];
|
|
|
|
var left = [parameters objectAtIndex:0],
|
|
right = [parameters objectAtIndex:1];
|
|
|
|
return [CPNumber numberWithInt:([left intValue] % [right intValue])];
|
|
}
|
|
|
|
|
|
- (id)first:(CPArray)parameters
|
|
{
|
|
if (_argc == 0)
|
|
[CPException raise:CPInvalidArgumentException reason:"Invalid number of parameters"];
|
|
|
|
return [[parameters objectAtIndex:0] objectAtIndex:0];
|
|
}
|
|
|
|
- (id)last:(CPArray)parameters
|
|
{
|
|
if (_argc == 0)
|
|
[CPException raise:CPInvalidArgumentException reason:"Invalid number of parameters"];
|
|
|
|
return [[parameters objectAtIndex:0] lastObject];
|
|
}
|
|
|
|
- (CPNumber)chs:(CPArray)parameters
|
|
{
|
|
if (_argc == 0)
|
|
[CPException raise:CPInvalidArgumentException reason:"Invalid number of parameters"];
|
|
|
|
return [CPNumber numberWithInt: - [[parameters objectAtIndex:0] intValue]];
|
|
}
|
|
|
|
- (id)index:(CPArray)parameters
|
|
{
|
|
if (_argc < 2)
|
|
[CPException raise:CPInvalidArgumentException reason:"Invalid number of parameters"];
|
|
|
|
var left = [parameters objectAtIndex:0],
|
|
right = [parameters objectAtIndex:1];
|
|
|
|
if ([left isKindOfClass: [CPDictionary class]])
|
|
return [left objectForKey:right];
|
|
else
|
|
return [left objectAtIndex: [right intValue]];
|
|
}
|
|
|
|
/*
|
|
- (CPNumber)median:(CPArray)parameters
|
|
{
|
|
}
|
|
- (CPNumber)mode:(CPArray)parameters
|
|
{
|
|
}
|
|
- (CPNumber)stddev:(CPArray)parameters
|
|
{
|
|
}
|
|
- (CPNumber)log:(CPArray)parameters
|
|
{
|
|
}
|
|
- (CPNumber)raise:to:(CPArray)parameters
|
|
{
|
|
}
|
|
- (CPNumber)trunc:(CPArray)parameters
|
|
{
|
|
}
|
|
|
|
// These functions are used when parsing
|
|
*/
|
|
|
|
@end
|
|
|