Objective-C: steps 5-A, self-hosting, perf, README
[jackhill/mal.git] / objc / types.m
1 #import "types.h"
2
3 @implementation MalTrue
4 @end
5
6 @implementation MalFalse
7 @end
8
9
10 // NSString subclassing based on:
11 // http://stackoverflow.com/a/21331422/471795
12
13 // Symbols
14
15 @interface MalSymbol ()
16 @property (nonatomic, strong) NSString *stringHolder;
17 @end
18
19 @implementation MalSymbol
20
21 - (instancetype)initWithCharactersNoCopy:(unichar *)characters length:(NSUInteger)length freeWhenDone:(BOOL)freeBuffer {
22 self = [super init];
23 if (self) {
24 self.stringHolder = [[NSString alloc] initWithCharactersNoCopy:characters length:length freeWhenDone:freeBuffer];
25 }
26 return self;
27 }
28
29 - (NSUInteger)length {
30 return self.stringHolder.length;
31 }
32
33 - (unichar)characterAtIndex:(NSUInteger)index {
34 return [self.stringHolder characterAtIndex:index];
35 }
36
37 @end
38
39
40 BOOL string_Q(id obj) {
41 if ([obj isKindOfClass:[NSString class]]) {
42 NSString * s = obj;
43 if (![s isKindOfClass:[MalSymbol class]]) {
44 return ![s hasPrefix:@"\u029e"];
45 }
46 }
47 return false;
48 }
49
50 // Lists
51
52 BOOL list_Q(id obj) {
53 return ([obj isKindOfClass:[NSArray class]] &&
54 ![obj isKindOfClass:[MalVector class]]);
55 }
56
57 NSArray * _rest(NSArray * obj) {
58 return [obj subarrayWithRange:NSMakeRange(1, [obj count]-1)];
59 }
60
61 // Vectors
62
63 @implementation MalVector
64
65 @synthesize array = _array;
66 @synthesize count = _count;
67
68 - (id)initWithArray:(NSArray *)arr {
69 self = [super init];
70 if (self) {
71 _array = arr;
72 _count = [arr count];
73 }
74 return self;
75 }
76
77 - (id)init {
78 return [self initWithArray:@[]];
79 }
80
81 + (id)fromArray:(NSArray *)arr {
82 return [[MalVector alloc] initWithArray:arr];
83 }
84
85 - (id)objectAtIndex:(NSUInteger)index {
86 return _array[index];
87 }
88
89 @end
90
91
92 // Hash Maps
93
94 NSDictionary * assoc_BANG(NSMutableDictionary * d, NSArray * kvs) {
95 for (int i=0; i < [kvs count]; i+=2) {
96 d[kvs[i]] = kvs[i+1];
97 }
98 return d;
99 }
100
101 NSDictionary * hash_map(NSArray *kvs) {
102 return assoc_BANG([NSMutableDictionary dictionary], kvs);
103 }
104
105
106 // Mal Functions
107
108 BOOL block_Q(id obj) {
109 id block = ^{};
110 Class blockClass = [block class];
111 while ([blockClass superclass] != [NSObject class]) {
112 blockClass = [blockClass superclass];
113 }
114 return [obj isKindOfClass:blockClass];
115 }
116
117
118
119 @implementation MalAtom
120
121 @synthesize val = _val;
122
123 - (id)init:(NSObject *)val {
124 self = [super init];
125 if (self) {
126 _val = val;
127 }
128 return self;
129 }
130
131 + (id)fromObject:(NSObject *)val {
132 return [[MalAtom alloc] init:val];
133 }
134
135 @end
136
137 BOOL atom_Q(id obj) {
138 return [obj isKindOfClass:[MalAtom class]];
139 }
140
141 // General functions
142
143 BOOL sequential_Q(NSObject * obj) {
144 return [obj isKindOfClass:[NSArray class]];
145 }
146
147 BOOL equal_Q(NSObject * a, NSObject * b) {
148 //NSLog(@"= %@ (%@), %@ (%@)", a, [a class], b, [b class]);
149 if (!(([a class] == [b class]) ||
150 ([a isKindOfClass:[NSArray class]] &&
151 [b isKindOfClass:[NSArray class]]) ||
152 ([a isKindOfClass:[NSNumber class]] &&
153 [b isKindOfClass:[NSNumber class]]))) {
154 return false;
155 }
156 if ([a isKindOfClass:[MalTrue class]]) {
157 return true;
158 } else if ([a isKindOfClass:[MalFalse class]]) {
159 return true;
160 } else if ([a isKindOfClass:[NSNumber class]]) {
161 return [(NSNumber *)a intValue] == [(NSNumber *)b intValue];
162 } else {
163 return [a isEqual:b];
164 }
165 }