1 #import
<Foundation
/Foundation.h
>
3 #import "mal_readline.h"
12 NSObject
*READ
(NSString
*str
) {
17 NSObject
*eval_ast
(NSObject
*ast
, Env
*env
) {
18 if ([ast isMemberOfClass
:[MalSymbol
class]]) {
19 return [env
get:(MalSymbol
*)ast
];
20 } else if ([ast isKindOfClass
:[NSArray
class]]) {
21 NSMutableArray
*newLst
= [NSMutableArray array
];
22 for (NSObject
* x in
(NSArray
*)ast
) {
23 [newLst addObject
:EVAL(x
, env
)];
25 if ([ast isKindOfClass
:[MalVector
class]]) {
26 return [MalVector fromArray
:newLst
];
30 } else if ([ast isKindOfClass
:[NSDictionary
class]]) {
31 NSMutableDictionary
*newDict
= [NSMutableDictionary dictionary
];
32 for (NSString
* k in
(NSDictionary
*)ast
) {
33 newDict
[k
] = EVAL(((NSDictionary
*)ast
)[k
], env
);
41 NSObject
*EVAL(NSObject
*ast
, Env
*env
) {
42 //NSLog
(@"
EVAL: %@ (%@)", _pr_str(ast, true), env);
44 return eval_ast
(ast
, env
);
47 NSArray
* alst
= (NSArray
*)ast
;
49 NSString
* a0sym
= [a0 isKindOfClass
:[MalSymbol
class]] ?
(NSString
*)a0
52 if ([a0sym isEqualTo
:@"def
!"
]) {
53 return [env
set:((MalSymbol
*)alst
[1]) val
:EVAL(alst
[2], env
)];
54 } else if ([(NSString
*)a0 isEqualTo
:@"let
*"
]) {
55 Env
*let_env
= [Env fromOuter
:env
];
56 NSArray
* binds
= (NSArray
*)alst
[1];
57 for (int i
=0; i
< [binds count
]; i
+=2) {
58 [let_env
set:binds
[i
] val
:EVAL(binds
[i
+1], let_env
)];
60 return EVAL(alst
[2], let_env
);
61 } else if ([a0sym isEqualTo
:@"do"
]) {
62 NSArray
* el
= (NSArray
*)eval_ast
(_rest
(alst
), env
);
63 return [el lastObject
];
64 } else if ([a0sym isEqualTo
:@"
if"
]) {
65 NSObject
* cond = EVAL(alst
[1], env
);
66 if ([cond isKindOfClass
:[NSNull
class]] ||
67 [cond isKindOfClass
:[MalFalse
class]]) {
68 if ([alst count
] > 3) {
69 return EVAL(alst
[3], env
);
71 return [NSNull alloc
];
74 return EVAL(alst
[2], env
);
76 } else if ([a0sym isEqualTo
:@"fn
*"
]) {
77 return [[MalFunc alloc
] init
:alst
[2] env
:env params
:alst
[1]];
79 NSArray
* el
= (NSArray
*) eval_ast
(ast
, env
);
84 return apply
(el
[0], args
);
86 if ([el[0] isKindOfClass:[MalFunc class]]) {
88 return [mf apply:args];
90 NSObject * (^ f)(NSArray *) = el[0];
98 NSString
*PRINT(NSObject
*exp) {
99 return _pr_str
(exp, true
);
103 NSString
*REP
(NSString
*line, Env
*env
) {
104 return PRINT(EVAL(READ
(line), env
));
108 Env
* repl_env
= [[Env alloc
] init
];
110 // Create an autorelease pool to manage the
memory into the program
111 NSAutoreleasePool
* pool
= [[NSAutoreleasePool alloc
] init
];
112 // If using automatic reference counting
(ARC
), use @autoreleasepool instead
:
113 // @autoreleasepool
{
115 // core.m
: defined using Objective
-C
116 NSDictionary
* core_ns
= [Core ns
];
117 for (NSString
* key in core_ns
) {
118 [repl_env
set:(MalSymbol
*)key val
:[core_ns objectForKey
:key
]];
121 // core.mal
: defined using the language itself
122 REP
(@"
(def
! not
(fn
* (a
) (if a false true
)))"
, repl_env
);
125 char *rawline
= _readline
("user
> "
);
126 if (!rawline
) { break; }
127 NSString
*line = [NSString stringWithUTF8String
:rawline
];
128 if ([line length] == 0) { continue
; }
130 printf
("
%s\n", [[REP(line, repl_env) description] UTF8String]);
131 } @
catch(NSString
*e
) {
132 printf
("
Error: %s\n", [e UTF8String]);
133 } @
catch(NSException
*e
) {
134 if ([[e name
] isEqualTo
:@"ReaderContinue"
]) { continue
; }
135 printf
("Exception
: %s\n", [[e reason] UTF8String]);