DISABLE FDs (REMOVE ME).
[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
203e9599
JM
52 // apply list
53 if ([(NSArray *)ast count] == 0) {
54 return ast;
55 }
57350ed7
JM
56 NSArray * el = (NSArray *) eval_ast(ast, env);
57 NSObject * (^ f)(NSArray *) = el[0];
7cae6e6f 58 NSArray * args = _rest(el);
57350ed7
JM
59 return f(args);
60}
61
62// print
63NSString *PRINT(NSObject *exp) {
64 return _pr_str(exp, true);
65}
66
67// REPL
68NSString *REP(NSString *line, NSDictionary *env) {
69 return PRINT(EVAL(READ(line), env));
70}
71
7cae6e6f 72int main () {
57350ed7
JM
73 NSDictionary * repl_env = @{
74 @"+": ^(NSArray *args){
75 return [NSNumber numberWithInt:[args[0] intValue] + [args[1] intValue]];
76 },
77 @"-": ^(NSArray *args){
78 return [NSNumber numberWithInt:[args[0] intValue] - [args[1] intValue]];
79 },
80 @"*": ^(NSArray *args){
81 return [NSNumber numberWithInt:[args[0] intValue] * [args[1] intValue]];
82 },
83 @"/": ^(NSArray *args){
84 return [NSNumber numberWithInt:[args[0] intValue] / [args[1] intValue]];
85 },
86 };
87
7cae6e6f
JM
88 // Create an autorelease pool to manage the memory into the program
89 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
90 // If using automatic reference counting (ARC), use @autoreleasepool instead:
91// @autoreleasepool {
92
57350ed7
JM
93 while (true) {
94 char *rawline = _readline("user> ");
95 if (!rawline) { break; }
96 NSString *line = [NSString stringWithUTF8String:rawline];
97 if ([line length] == 0) { continue; }
98 @try {
99 printf("%s\n", [[REP(line, repl_env) description] UTF8String]);
100 } @catch(NSString *e) {
101 printf("Error: %s\n", [e UTF8String]);
7cae6e6f
JM
102 } @catch(NSException *e) {
103 if ([[e name] isEqualTo:@"ReaderContinue"]) { continue; }
104 printf("Exception: %s\n", [[e reason] UTF8String]);
57350ed7
JM
105 }
106 }
107
108 [pool drain];
109
110// }
111}