Objective-C: steps 5-A, self-hosting, perf, README
[jackhill/mal.git] / objc / step2_eval.m
CommitLineData
57350ed7
JM
1#import <Foundation/Foundation.h>
2
3#import "mal_readline.h"
4#import "types.h"
5#import "reader.h"
6#import "printer.h"
7
8// read
9NSObject *READ(NSString *str) {
10 return read_str(str);
11}
12
13// eval
14
15// forward declaration
16NSObject *EVAL(NSObject *ast, NSDictionary *env);
17
18NSObject *eval_ast(NSObject *ast, NSDictionary *env) {
19 if ([ast isMemberOfClass:[MalSymbol class]]) {
20 if ([env objectForKey:ast]) {
21 return env[ast];
22 } else {
23 @throw [NSString stringWithFormat:@"'%@' not found", ast];
24 }
25 } else if ([ast isKindOfClass:[NSArray class]]) {
26 NSMutableArray *newLst = [NSMutableArray array];
27 for (NSObject * x in (NSArray *)ast) {
28 [newLst addObject:EVAL(x, env)];
29 }
30 if ([ast isKindOfClass:[MalVector class]]) {
31 return [MalVector fromArray:newLst];
32 } else {
33 return newLst;
34 }
35 } else if ([ast isKindOfClass:[NSDictionary class]]) {
36 NSMutableDictionary *newDict = [NSMutableDictionary dictionary];
37 for (NSString * k in (NSDictionary *)ast) {
38 newDict[k] = EVAL(((NSDictionary *)ast)[k], env);
39 }
40 return newDict;
41 } else {
42 return ast;
43 }
44}
45
46NSObject *EVAL(NSObject *ast, NSDictionary *env) {
47 //NSLog(@"EVAL: %@", ast);
48 if (!list_Q(ast)) {
49 return eval_ast(ast, env);
50 }
51
52 NSArray * el = (NSArray *) eval_ast(ast, env);
53 NSObject * (^ f)(NSArray *) = el[0];
7cae6e6f 54 NSArray * args = _rest(el);
57350ed7
JM
55 return f(args);
56}
57
58// print
59NSString *PRINT(NSObject *exp) {
60 return _pr_str(exp, true);
61}
62
63// REPL
64NSString *REP(NSString *line, NSDictionary *env) {
65 return PRINT(EVAL(READ(line), env));
66}
67
7cae6e6f 68int main () {
57350ed7
JM
69 NSDictionary * repl_env = @{
70 @"+": ^(NSArray *args){
71 return [NSNumber numberWithInt:[args[0] intValue] + [args[1] intValue]];
72 },
73 @"-": ^(NSArray *args){
74 return [NSNumber numberWithInt:[args[0] intValue] - [args[1] intValue]];
75 },
76 @"*": ^(NSArray *args){
77 return [NSNumber numberWithInt:[args[0] intValue] * [args[1] intValue]];
78 },
79 @"/": ^(NSArray *args){
80 return [NSNumber numberWithInt:[args[0] intValue] / [args[1] intValue]];
81 },
82 };
83
7cae6e6f
JM
84 // Create an autorelease pool to manage the memory into the program
85 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
86 // If using automatic reference counting (ARC), use @autoreleasepool instead:
87// @autoreleasepool {
88
57350ed7
JM
89 while (true) {
90 char *rawline = _readline("user> ");
91 if (!rawline) { break; }
92 NSString *line = [NSString stringWithUTF8String:rawline];
93 if ([line length] == 0) { continue; }
94 @try {
95 printf("%s\n", [[REP(line, repl_env) description] UTF8String]);
96 } @catch(NSString *e) {
97 printf("Error: %s\n", [e UTF8String]);
7cae6e6f
JM
98 } @catch(NSException *e) {
99 if ([[e name] isEqualTo:@"ReaderContinue"]) { continue; }
100 printf("Exception: %s\n", [[e reason] UTF8String]);
57350ed7
JM
101 }
102 }
103
104 [pool drain];
105
106// }
107}