1 #import
<Foundation
/Foundation.h
>
3 #import "mal_readline.h"
9 #import
<objc
/runtime.h
>
11 NSObject
* wrap_tf
(BOOL val
) {
12 return val ?
[MalTrue alloc
] : [MalFalse alloc
];
17 + (NSDictionary
*)ns
{
19 @"
="
: ^
(NSArray
*args
){
20 return wrap_tf
(equal_Q
(args
[0], args
[1]));
22 @"throw"
: ^
(NSArray
*args
){
26 @"nil?"
: ^
(NSArray
*args
){
27 return wrap_tf
([args
[0] isKindOfClass
:[NSNull
class]]);
29 @"true?"
: ^
(NSArray
*args
){
30 return wrap_tf
([args
[0] isKindOfClass
:[MalTrue
class]]);
32 @"false?"
: ^
(NSArray
*args
){
33 return wrap_tf
([args
[0] isKindOfClass
:[MalFalse
class]]);
35 @"string?"
: ^
(NSArray
*args
){
36 return wrap_tf
(string_Q
(args
[0]));
38 @"symbol"
: ^
(NSArray
*args
){
39 return [MalSymbol stringWithString
:args
[0]];
41 @"symbol?"
: ^
(NSArray
*args
){
42 return wrap_tf
([args
[0] isKindOfClass
:[MalSymbol
class]]);
44 @"keyword"
: ^
(NSArray
*args
){
45 return [NSString stringWithFormat
:@"
\u029e%@", args[0]];
47 @"keyword?"
: ^
(NSArray
*args
){
48 return wrap_tf
([args
[0] isKindOfClass
:[NSString
class]] &&
49 ![args
[0] isKindOfClass
:[MalSymbol
class]] &&
52 @"number?"
: ^
(NSArray
*args
){
53 return wrap_tf
([args
[0] isKindOfClass
:[NSNumber
class]]);
55 @"fn?"
: ^
(NSArray
*args
){
56 return wrap_tf
(block_Q
(args
[0]) ||
57 ([args
[0] isKindOfClass
:[MalFunc
class]] && ![(MalFunc
*)args
[0] isMacro
]));
59 @"macro?"
: ^
(NSArray
*args
){
60 return wrap_tf
([args
[0] isKindOfClass
:[MalFunc
class]] && [(MalFunc
*)args
[0] isMacro
]);
63 @"pr
-str"
: ^
(NSArray
*args
){
64 NSMutableArray
* res
= [NSMutableArray array
];
65 for (id e in args
) { [res addObject
:_pr_str
(e
,true
)]; }
66 return [res componentsJoinedByString
:@" "
];
68 @"str"
: ^
(NSArray
*args
){
69 NSMutableArray
* res
= [NSMutableArray array
];
70 for (id e in args
) { [res addObject
:_pr_str
(e
,false
)]; }
71 return [res componentsJoinedByString
:@""
];
73 @"prn"
: ^
(NSArray
*args
){
74 NSMutableArray
* res
= [NSMutableArray array
];
75 for (id e in args
) { [res addObject
:_pr_str
(e
,true
)]; }
76 printf
("
%s\n", [[res componentsJoinedByString:@" "] UTF8String]);
78 return [NSNull alloc
];
80 @"println"
: ^
(NSArray
*args
){
81 NSMutableArray
* res
= [NSMutableArray array
];
82 for (id e in args
) { [res addObject
:_pr_str
(e
,false
)]; }
83 printf
("
%s\n", [[res componentsJoinedByString:@" "] UTF8String]);
85 return [NSNull alloc
];
87 @"read
-string"
: ^
(NSArray
*args
){
88 return read_str
(args
[0]);
90 @"readline"
: ^
(NSArray
*args
){
91 char * rawline
= _readline
((char *)[(NSString
*)args
[0] UTF8String
]);
93 return (NSObject
*)[NSString stringWithUTF8String
:rawline
];
95 return (NSObject
*)[NSNull alloc
];
98 @"slurp"
: ^
(NSArray
*args
){
99 return [NSString stringWithContentsOfFile
:args
[0]
100 encoding
: NSUTF8StringEncoding
104 @"
<"
: ^
(NSArray
*args
){
105 return wrap_tf
([args
[0] intValue
] < [args
[1] intValue
]);
107 @"
<="
: ^
(NSArray
*args
){
108 return wrap_tf
([args
[0] intValue
] <= [args
[1] intValue
]);
110 @"
>"
: ^
(NSArray
*args
){
111 return wrap_tf
([args
[0] intValue
] > [args
[1] intValue
]);
113 @"
>="
: ^
(NSArray
*args
){
114 return wrap_tf
([args
[0] intValue
] >= [args
[1] intValue
]);
116 @"
+"
: ^
(NSArray
*args
){
117 return [NSNumber numberWithInt
:[args
[0] intValue
] + [args
[1] intValue
]];
119 @"
-"
: ^
(NSArray
*args
){
120 return [NSNumber numberWithInt
:[args
[0] intValue
] - [args
[1] intValue
]];
122 @"
*"
: ^
(NSArray
*args
){
123 return [NSNumber numberWithInt
:[args
[0] intValue
] * [args
[1] intValue
]];
125 @"
/"
: ^
(NSArray
*args
){
126 return [NSNumber numberWithInt
:[args
[0] intValue
] / [args
[1] intValue
]];
128 @"time
-ms"
: ^
(NSArray
*args
){
129 long long ms
= [[NSDate date
] timeIntervalSince1970
] * 1000;
130 return [NSNumber numberWithUnsignedInteger
:ms
];
133 @"list"
: ^
(NSArray
*args
){
136 @"list?"
: ^
(NSArray
*args
){
137 return wrap_tf
(list_Q
(args
[0]));
139 @"vector"
: ^
(NSArray
*args
){
140 return [MalVector fromArray
:args
];
142 @"vector?"
: ^
(NSArray
*args
){
143 return wrap_tf
([args
[0] isKindOfClass
:[MalVector
class]]);
145 @"hash
-map"
: ^
(NSArray
*args
){
146 return hash_map
(args
);
148 @"map?"
: ^
(NSArray
*args
){
149 return wrap_tf
([args
[0] isKindOfClass
:[NSDictionary
class]]);
151 @"assoc"
: ^
(NSArray
*args
){
152 NSDictionary
* dict
= args
[0];
153 NSMutableDictionary
* new_dict
= [[NSMutableDictionary alloc
]
154 initWithDictionary
:dict
156 return assoc_BANG
(new_dict
, _rest
(args
));
158 @"dissoc"
: ^
(NSArray
*args
){
159 NSDictionary
* dict
= args
[0];
160 NSMutableDictionary
* new_dict
= [[NSMutableDictionary alloc
]
161 initWithDictionary
:dict
163 for (NSString
* key in _rest
(args
)) {
164 [new_dict removeObjectForKey
:key
];
168 @"
get"
: ^
(NSArray
*args
){
169 if ([args
[0] isKindOfClass
:[NSNull
class]]) {
170 return (NSObject
*)[NSNull alloc
];
172 NSObject
* res
= ((NSDictionary
*)args
[0])[args
[1]];
173 return res ? res
: [NSNull alloc
];
175 @"contains?"
: ^
(NSArray
*args
){
176 if ([args
[0] isKindOfClass
:[NSNull
class]]) {
177 return wrap_tf
(false
);
179 return wrap_tf
(((NSDictionary
*)args
[0])[args
[1]] != nil
);
181 @"keys"
: ^
(NSArray
*args
){
182 return [(NSDictionary
*)args
[0] allKeys
];
184 @"vals"
: ^
(NSArray
*args
){
185 return [(NSDictionary
*)args
[0] allValues
];
188 @"sequential?"
: ^
(NSArray
*args
){
189 return wrap_tf
([args
[0] isKindOfClass
:[NSArray
class]]);
191 @"cons"
: ^
(NSArray
*args
){
192 NSMutableArray
* res
= [NSMutableArray array
];
193 [res addObject
:args
[0]];
194 [res addObjectsFromArray
:args
[1]];
197 @"concat"
: ^
(NSArray
*args
){
198 NSMutableArray
* res
= [NSMutableArray array
];
199 for (NSArray
* arr in args
) {
200 [res addObjectsFromArray
:arr
];
204 @"nth"
: ^
(NSArray
*args
){
205 NSArray
* lst
= (NSArray
*)args
[0];
206 int idx
= [(NSNumber
*)args
[1] intValue
];
207 if (idx
< [lst count
]) {
210 @throw @"nth
: index out of range"
;
213 @"first"
: ^
(NSArray
*args
){
214 if ([args
[0] isKindOfClass
:[NSNull
class]]) {
215 return (NSObject
*)[NSNull alloc
];
217 NSArray
* lst
= (NSArray
*)args
[0];
218 if ([lst count
] > 0) {
219 return (NSObject
*)lst
[0];
221 return (NSObject
*)[NSNull alloc
];
224 @"rest"
: ^
(NSArray
*args
){
225 if ([args
[0] isKindOfClass
:[NSNull
class]]) {
228 NSArray
* lst
= (NSArray
*)args
[0];
229 if ([lst count
] > 1) {
235 @"empty?"
: ^
(NSArray
*args
){
236 if ([args
[0] isKindOfClass
:[NSNull
class]]) {
237 return wrap_tf
(true
);
239 return wrap_tf
([args
[0] count
] == 0);
242 @"count"
: ^
(NSArray
*args
){
243 if ([args
[0] isKindOfClass
:[NSNull
class]]) {
246 return [NSNumber numberWithInt
:[args
[0] count
]];
249 @"apply"
: ^
(NSArray
*args
){
250 NSObject
* (^ f
)(NSArray
*) = args
[0];
251 NSMutableArray
* fargs
= [NSMutableArray array
];
252 if ([args count
] > 1) {
253 NSRange r
= NSMakeRange
(1, [args count
]-2);
254 [fargs addObjectsFromArray
:[args subarrayWithRange
:r
]];
256 [fargs addObjectsFromArray
:(NSArray
*)[args lastObject
]];
257 return apply
(f
, fargs
);
259 @"map"
: ^
(NSArray
*args
){
260 NSObject
* (^ f
)(NSArray
*) = args
[0];
261 NSMutableArray
* res
= [NSMutableArray array
];
262 for (NSObject
* x in
(NSArray
*)args
[1]) {
263 [res addObject
:apply
(f
, @
[x
])];
267 @"
conj"
: ^
(NSArray
*args
){
268 NSMutableArray
* res
= [NSMutableArray array
];
269 if ([args
[0] isKindOfClass
:[MalVector
class]]) {
270 [res addObjectsFromArray
:args
[0]];
271 [res addObjectsFromArray
:_rest
(args
)];
272 return (NSObject
*)[MalVector fromArray
:res
];
274 [res addObjectsFromArray
:[[_rest
(args
) reverseObjectEnumerator
]
276 [res addObjectsFromArray
:args
[0]];
277 return (NSObject
*)res
;
280 @"seq"
: ^
(NSArray
*args
){
281 if (list_Q
(args
[0])) {
282 if ([args
[0] count
] == 0) { return (NSObject
*)[NSNull alloc
]; }
283 return (NSObject
*)args
[0];
284 } else if ([args
[0] isKindOfClass
:[MalVector
class]]) {
285 if ([args
[0] count
] == 0) { return (NSObject
*)[NSNull alloc
]; }
286 return (NSObject
*)[NSArray arrayWithArray
:args
[0]];
287 } else if (string_Q
(args
[0])) {
288 NSString
* str
= args
[0];
289 if ([str
length] == 0) { return (NSObject
*)[NSNull alloc
]; }
290 NSMutableArray
* res
= [NSMutableArray array
];
291 for (int i
=0; i
< [str
length]; i
++) {
292 char c
= [str characterAtIndex
:i
];
293 [res addObject
:[NSString stringWithFormat
:@"
%c", c]];
295 return (NSObject
*)res
;
296 } else if ([args
[0] isKindOfClass
:[NSNull
class]]) {
297 return (NSObject
*)args
[0];
299 @throw @"seq
: called on non
-sequence"
;
303 @"
meta"
: ^id
(NSArray
*args
){
304 if ([args
[0] isKindOfClass
:[MalFunc
class]]) {
305 return [(MalFunc
*)args
[0] meta];
307 id res
= objc_getAssociatedObject
(args
[0], @"
meta"
);
308 return res ? res
: (NSObject
*)[NSNull alloc
];
311 @"with
-meta"
: ^id
(NSArray
*args
){
312 if ([args
[0] isKindOfClass
:[MalFunc
class]]) {
313 MalFunc
* cmf
= [(MalFunc
*)args
[0] copy
];
316 } else if (!block_Q
(args
[0])) {
317 id res
= [args
[0] copy
];
318 objc_setAssociatedObject
(res
, @"
meta"
, args
[1], OBJC_ASSOCIATION_RETAIN_NONATOMIC
);
321 id
(^blk
)(NSArray
*args
) = args
[0];
322 id
(^wrapBlock
)(NSArray
*args
) = ^id
(NSArray
*args
) { return blk
(args
); };
323 id
(^res
)(NSArray
*args
) = [wrapBlock copy
]; // under mrc
: copy to
get a malloc block instead of a stack block.
324 objc_setAssociatedObject
(res
, @"
meta"
, args
[1], OBJC_ASSOCIATION_RETAIN_NONATOMIC
);
328 @"atom"
: ^
(NSArray
*args
){
329 return [MalAtom fromObject
:args
[0]];
331 @"atom?"
: ^
(NSArray
*args
){
332 return wrap_tf
(atom_Q
(args
[0]));
334 @"deref"
: ^
(NSArray
*args
){
335 return [(MalAtom
*)args
[0] val
];
337 @"
reset!"
: ^
(NSArray
*args
){
338 MalAtom
* atm
= (MalAtom
*)args
[0];
339 return atm.val
= args
[1];
341 @"swap
!"
: ^
(NSArray
*args
){
342 MalAtom
* atm
= (MalAtom
*)args
[0];
343 NSObject
* (^ f
)(NSArray
*) = args
[1];
344 NSMutableArray
* fargs
= [NSMutableArray array
];
345 [fargs addObject
:atm.val
];
346 if ([args count
] > 2) {
347 NSRange r
= NSMakeRange
(2, [args count
]-2);
348 [fargs addObjectsFromArray
:[args subarrayWithRange
:r
]];
350 return atm.val
= apply
(f
, fargs
);