Source

Silver / Classes / Types / SVModule.m

//
//  SVModule.m
//  Silver
//
//  Created by Michael Tindal on 2/4/12.
//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//

#import "SVModule.h"
#import "SVFunction.h"
#import "SVCategory.h"
#import "NSMutableDictionary+SVExtensions.h"
#import "SVControlOperations.h"
#import "SVVariableAssignment.h"
#import "SVVariable.h"
#import "SVClassWrapper.h"
#import "SVClass.h"
#import "SVCategory.h"
#import "SVProtocol.h"
#import "SVIncludeStatement.h"
#import <objc/runtime.h>

@interface SVClass ()

@property (retain) NSMutableArray * contents;

@end

@implementation SVModule

+ (SVModule *) moduleWithName:(NSString *)name contents:(NSMutableArray *)contents {
    return [[self alloc] initWithName:name contents:contents];
}

- (id) initWithName:(NSString *)name contents:(NSMutableArray *)contents {
    if((self = [super init])) {
        self.name = name;
        self.contents = contents;
        mappedContents_ = [NSMutableDictionary dictionary];
    }
    return self;
}

- (id) evaluateWithContext:(NSMutableDictionary *)context {
    NSMutableDictionary * _context = [NSMutableDictionary dictionary];
    [_context setObject:context forKey:SV_PARENT_CONTEXT_KEY];
    [_context setObject:BL(YES) forKey:self.name];
    [context createSymbolTable];
    SVSymbolTable * table = [context objectForKey:@"__SV_CLASS_DEF"] ? [context symbolTable] : [SVSymbolTable sharedTable];
    [_context setObject:self.name forKey:@"__SV_CLASS_DEF"];
    
    
    /* Now two-pass to check for include statements */
    NSMutableArray* contents = [NSMutableArray array];
    for (id content in self.contents) {
        if([content isKindOfClass:[SVIncludeStatement class]]) {
            id res = [content evaluateWithContext:context];
            if([res respondsToSelector:@selector(contents)]) {
                [contents addObjectsFromArray:[res contents]];
            } else {
                [contents addObject:res];
            }
        } else {
            [contents addObject:content];
        }
    }
    
    for (id content in contents) {
        if([content isKindOfClass:[SVClass class]] || [content isKindOfClass:[SVFunction class]] || [content isKindOfClass:[SVCategory class]]) {
            if(![content isKindOfClass:[SVCategory class]]) {
                [self.mappedContents setObject:content forKey:[content name]]; 
            } else {
                [self.mappedContents setObject:content forKey:[content className]];
            }
        }
    }
    
    SVSymbol * modsym = [table symbolWithName:self.name];
    modsym.value = self;
    
    return self;

}
@synthesize mappedContents = mappedContents_;
@end

@implementation SVSubmodulePart

+(SVSubmodulePart *) subModule:(NSString *)submodule fromOwner:(id)owner {
    return [[self alloc] initWithSubModule:submodule fromOwner:owner];
}

-(id) initWithSubModule:(NSString *)submodule fromOwner:(id)owner {
    if((self = [super init])) {
        self.submodule = submodule;
        self.owner = owner;
    }
    return self;
}

-(id) evaluateWithContext:(NSMutableDictionary *)context {
    id res = [self.owner evaluateWithContext:context];
    if(![res isKindOfClass:[SVModule class]])
        return nil;
    return [((SVModule *)res).mappedContents objectForKey:self.submodule];
}

@synthesize owner = owner_, submodule = submodule_;

@end