// // MPFunction.m // MathPad // // Created by Kim Wittenburg on 18.04.14. // Copyright (c) 2014 Kim Wittenburg. All rights reserved. // #import "MPFunction.h" #import "MPExpression.h" #import "MPRangePath.h" #import "NSIndexPath+MPAdditions.h" #import "MPFunctionTerm.h" @implementation MPFunction #pragma mark Creation Methods - (instancetype)init { self = [super init]; if (self) { for (NSString *key in self.childrenAccessors) { MPExpression *emptyExpression = [[MPExpression alloc] init]; emptyExpression.parent = self; [self setValue:emptyExpression forKey:key]; } } return self; } #pragma mark Working With the Expression Tree - (MPExpression *)rootExpression { return [self.parent rootExpression]; } - (NSIndexPath *)indexPath { if (!self.parent) { return nil; } NSUInteger selfIndex = [self.parent indexOfElement:self]; return [[self.parent indexPath] indexPathByAddingIndex:selfIndex]; } - (NSUInteger)numberOfChildren { return self.childrenAccessors.count; } - (MPExpression *)childAtIndex:(NSUInteger)index { return [self valueForKey:self.childrenAccessors[index]]; } - (void)setChild:(MPExpression *)child atIndex:(NSUInteger)index { [[self valueForKey:self.childrenAccessors[index]] setParent:nil]; [self setValue:child forKey:self.childrenAccessors[index]]; child.parent = self; [self didChangeChildAtIndex:index]; } - (NSArray *)children { NSUInteger childCount = [self numberOfChildren]; NSMutableArray *children = [[NSMutableArray alloc] initWithCapacity:childCount]; for (NSInteger i = 0; i < childCount; i++) { [children addObject:[self childAtIndex:i]]; } return [children copy]; } - (NSUInteger)indexOfChild:(MPExpression *)child { NSUInteger index = 0; for (; index < [self numberOfChildren]; index++) { if ([self childAtIndex:index] == child) { return index; } } return NSNotFound; } - (id)elementAtIndexPath:(NSIndexPath *)indexPath { if (indexPath.length == 0) { return self; } MPExpression *child = [self childAtIndex:[indexPath indexAtPosition:0]]; return [child elementAtIndexPath:[indexPath indexPathByRemovingFirstIndex]]; } #pragma mark Notifications - (void)didChangeElementsInRangePath:(MPRangePath *)rangePath replacementLength:(NSUInteger)replacementLength { NSUInteger selfIndex = [self.parent indexOfElement:self]; MPRangePath *newPath = MPMakeRangePath([rangePath.location indexPathByPreceedingIndex:selfIndex], rangePath.length); [self.parent didChangeElementsInRangePath:newPath replacementLength:replacementLength]; } - (void)didChangeChildAtIndex:(NSUInteger)index { MPRangePath *path = [[MPRangePath alloc] initWithRange:NSMakeRange(index, 1)]; [self didChangeElementsInRangePath:path replacementLength:1]; } #pragma mark Evaluating Functions - (BOOL)expectsVariableDefinitionInChildAtIndex:(NSUInteger)index { return NO; } #pragma mark Working With Functions - (NSString *)description { return @"[]"; } #pragma mark - NSCopying - (id)copyWithZone:(NSZone *)zone { id copy = [[self.class allocWithZone:zone] init]; for (NSString *key in self.childrenAccessors) { MPExpression *child = [[self valueForKey:key] copy]; [copy setValue:child forKey:key]; } return copy; } #pragma mark - NSCoding - (id)initWithCoder:(NSCoder *)aDecoder { self = [super init]; if (self) { NSArray *children = [aDecoder decodeObject]; NSInteger index = 0; for (MPExpression *child in children) { [self setChild:child atIndex:index]; ++index; } } return self; } - (void)encodeWithCoder:(NSCoder *)aCoder { [aCoder encodeObject:self.children]; } #pragma mark - MPExpressionElement - (BOOL)isString { return NO; } - (BOOL)isFunction { return YES; } - (NSUInteger)length { return 1; } @end