This repository has been archived by the owner on Jan 13, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 27
/
MOCInterpreter.m
130 lines (95 loc) · 3.7 KB
/
MOCInterpreter.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
//
// MOCInterpreter.m
// mocha
//
// Created by Logan Collins on 5/12/12.
// Copyright (c) 2012 Sunflower Softworks. All rights reserved.
//
#import "MOCInterpreter.h"
#import <JavaScriptCore/JavaScriptCore.h>
#import <Mocha/MochaRuntime_Private.h>
#import <stdio.h>
#import <stdlib.h>
#import <string.h>
#import <readline/readline.h>
#import <readline/history.h>
static const char interactivePrompt[] = "> ";
static char ** runtimeCompletion(const char * text, int start, int end);
@interface MOCInterpreter ()
- (void)installBuiltins;
@end
@implementation MOCInterpreter
- (void)installBuiltins {
Mocha *runtime = [Mocha sharedRuntime];
MOMethod *gc = [MOMethod methodWithTarget:runtime selector:@selector(garbageCollect)];
[runtime setValue:gc forKey:@"gc"];
MOMethod *checkSyntax = [MOMethod methodWithTarget:runtime selector:@selector(isSyntaxValidForString:)];
[runtime setValue:checkSyntax forKey:@"checkSyntax"];
MOMethod *exit = [MOMethod methodWithTarget:self selector:@selector(exit)];
[runtime setValue:exit forKey:@"exit"];
}
- (void)run {
Mocha *runtime = [Mocha sharedRuntime];
[runtime setDelegate:self];
[self installBuiltins];
//rl_attempted_completion_function = runtimeCompletion;
//rl_bind_key('\t', rl_complete);
char *line = NULL;
while ((line = readline(interactivePrompt))) {
if (line[0]) {
add_history(line);
}
NSString *string = [NSString stringWithCString:(const char *)line encoding:NSUTF8StringEncoding];
if ([string length] > 0) {
@try {
JSValueRef value = [runtime evalJSString:string];
if (value != NULL) {
JSStringRef string = JSValueToStringCopy([runtime context], value, NULL);
NSString *description = (NSString *)CFBridgingRelease(JSStringCopyCFString(NULL, string));
JSStringRelease(string);
printf("%s\n", [description UTF8String]);
}
// Set the last result as the special variable "_"
id object = [runtime objectForJSValue:value];
if (object != nil) {
[runtime setValue:object forKey:@"_"];
}
else {
[runtime setNilValueForKey:@"_"];
}
}
@catch (NSException *e) {
if ([e userInfo] != nil) {
printf("%s: %s\n%s\n", [[e name] UTF8String], [[e reason] UTF8String], [[[e userInfo] description] UTF8String]);
}
else {
printf("%s: %s\n", [[e name] UTF8String], [[e reason] UTF8String]);
}
}
}
free(line);
}
}
- (void)exit {
exit(0);
}
@end
static char ** runtimeCompletion(const char * text, int start, int end) {
char ** matches = NULL;
Mocha *runtime = [Mocha sharedRuntime];
NSString *query = [NSString stringWithUTF8String:text];
NSArray *symbols = [[runtime globalSymbolNames] filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"self beginswith %@", query]];
NSUInteger count = [symbols count];
if (count > 0) {
matches = (char **)malloc(sizeof(char *) * ([symbols count] + 1));
for (NSUInteger i=0; i<count; i++) {
NSString *string = [symbols objectAtIndex:i];
char * aString = (char *)[string UTF8String];
char * name = (char *)malloc(strlen(aString) + 1);
strcpy(name, aString);
matches[i] = name;
}
matches[count] = NULL;
}
return matches;
}