ソースを参照

Get much closer to get something real up and running

This is about a day (and a half?) of work, mostly spent trying to
understand what planck is doing, and then porting code over,
occasionally chasing segfaults.

We can evaluate ClojureScript expressions now, but not require the
planck namespaces yet.  The errors point to missing files, but I'm
guessing that some of the `function_*` ports are incomplete.
Lucas Stadler 9 年 前
コミット
97e800fa5f
共有1 個のファイルを変更した276 個の追加15 個の削除を含む
  1. 276 15
      c/ton/main.c

+ 276 - 15
c/ton/main.c

@ -1,3 +1,5 @@
1
#include <assert.h>
2
#include <errno.h>
1 3
#include <stdio.h>
2 4
#include <stdlib.h>
3 5
#include <string.h>
@ -13,12 +15,27 @@ char console_log_buf[CONSOLE_LOG_BUF_SIZE];
13 15
JSStringRef to_string(JSContextRef ctx, JSValueRef val);
14 16
JSValueRef evaluate_script(JSContextRef ctx, char *script, char *source);
15 17
18
void evaluate_source(JSContextRef ctx, char *type, char *source_value, bool expression, char *set_ns);
16 19
char *munge(char *s);
17 20
18 21
void bootstrap(JSContextRef ctx, char *deps_file_path, char *goog_base_path);
22
JSObjectRef get_function(JSContextRef ctx, char *namespace, char *name);
19 23
20 24
char* get_contents(char *path);
21 25
26
void debug_print_value(char *prefix, JSContextRef ctx, JSValueRef exception) {
27
#ifdef DEBUG
28
	if (exception != NULL) {
29
		JSStringRef ex_str = to_string(ctx, exception);
30
		char ex_buf[1000];
31
		ex_buf[0] = '\0';
32
		JSStringGetUTF8CString(ex_str, ex_buf, 1000-1);
33
		printf("%s: %s\n", prefix, ex_buf);
34
		JSStringRelease(ex_str);
35
	}
36
#endif
37
}
38
22 39
JSValueRef function_console_log(JSContextRef ctx, JSObjectRef function, JSObjectRef this_object,
23 40
		size_t argc, const JSValueRef args[], JSValueRef* exception) {
24 41
	for (int i = 0; i < argc; i++) {
@ -51,6 +68,131 @@ JSValueRef function_console_error(JSContextRef ctx, JSObjectRef function, JSObje
51 68
	return JSValueMakeUndefined(ctx);
52 69
}
53 70
71
JSValueRef function_read_file(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject,
72
		size_t argc, const JSValueRef args[], JSValueRef* exception) {
73
	// TODO: implement fully
74
	fprintf(stderr, "WARN: %s: stub\n", __func__);
75
76
	if (argc == 1 && JSValueGetType(ctx, args[0]) == kJSTypeString) {
77
		char path[100];
78
		JSStringRef path_str = JSValueToStringCopy(ctx, args[0], NULL);
79
		JSStringGetUTF8CString(path_str, path, 100);
80
		JSStringRelease(path_str);
81
82
		debug_print_value
83
	("read_file", ctx, args[0]);
84
85
		char full_path[150];
86
		// TODO: should not load from here?
87
		snprintf(full_path, 150, "%s/%s", "out", path);
88
89
		char *contents = get_contents(full_path);
90
		JSStringRef contents_str = JSStringCreateWithUTF8CString(contents);
91
		free(contents);
92
93
		JSValueRef res[2];
94
		res[0] = JSValueMakeString(ctx, contents_str);
95
		res[1] = JSValueMakeNumber(ctx, 0);
96
		return JSObjectMakeArray(ctx, 2, res, NULL);
97
	}
98
99
	return JSValueMakeNull(ctx);
100
}
101
102
JSValueRef function_load(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject,
103
		size_t argc, const JSValueRef args[], JSValueRef* exception) {
104
	// TODO: implement fully
105
	fprintf(stderr, "WARN: %s: stub\n", __func__);
106
107
	if (argc == 1 && JSValueGetType(ctx, args[0]) == kJSTypeString) {
108
		char path[100];
109
		JSStringRef path_str = JSValueToStringCopy(ctx, args[0], NULL);
110
		JSStringGetUTF8CString(path_str, path, 100);
111
		JSStringRelease(path_str);
112
113
		debug_print_value
114
	("load", ctx, args[0]);
115
116
		char full_path[150];
117
		// TODO: should not load from here?
118
		snprintf(full_path, 150, "%s/%s", "out", path);
119
120
		char *contents = get_contents(full_path);
121
		JSStringRef contents_str = JSStringCreateWithUTF8CString(contents);
122
		free(contents);
123
124
		JSValueRef res[2];
125
		res[0] = JSValueMakeString(ctx, contents_str);
126
		res[1] = JSValueMakeNumber(ctx, 0);
127
		return JSObjectMakeArray(ctx, 2, res, NULL);
128
	}
129
130
	return JSValueMakeNull(ctx);
131
}
132
133
JSValueRef function_load_deps_cljs_files(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject,
134
		size_t argc, const JSValueRef args[], JSValueRef* exception) {
135
	// TODO: not implemented
136
	fprintf(stderr, "WARN: %s: stub\n", __func__);
137
	return JSObjectMakeArray(ctx, 0, NULL, NULL);
138
}
139
140
JSValueRef function_eval(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject,
141
		size_t argc, const JSValueRef args[], JSValueRef* exception) {
142
	JSValueRef val = NULL;
143
144
	if (argc == 2
145
		&& JSValueGetType(ctx, args[0]) == kJSTypeString
146
		&& JSValueGetType(ctx, args[1]) == kJSTypeString) {
147
		debug_print_value("eval", ctx, args[1]);
148
149
		JSStringRef sourceRef = JSValueToStringCopy(ctx, args[0], NULL);
150
		JSStringRef pathRef = JSValueToStringCopy(ctx, args[1], NULL);
151
152
		JSEvaluateScript(ctx, sourceRef, NULL, pathRef, 0, &val);
153
154
		JSStringRelease(pathRef);
155
		JSStringRelease(sourceRef);
156
	}
157
158
	return val != NULL ? val : JSValueMakeNull(ctx);
159
}
160
161
JSValueRef function_get_term_size(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject,
162
		size_t argc, const JSValueRef args[], JSValueRef* exception) {
163
	// TODO: not implemented
164
	fprintf(stderr, "WARN: %s: stub\n", __func__);
165
	return JSValueMakeNull(ctx);
166
}
167
168
JSValueRef function_print_fn(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject,
169
		size_t argc, const JSValueRef args[], JSValueRef* exception) {
170
	if (argc == 1 && JSValueIsString(ctx, args[0])) {
171
		JSStringRef val_str = JSValueToStringCopy(ctx, args[0], NULL);
172
		char buf[1000];
173
		JSStringGetUTF8CString(val_str, buf, 1000);
174
175
		fprintf(stdout, "%s", buf);
176
		fflush(stdout);
177
	}
178
179
	return JSValueMakeNull(ctx);
180
}
181
182
JSValueRef function_print_err_fn(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject,
183
		size_t argc, const JSValueRef args[], JSValueRef* exception) {
184
	if (argc == 1 && JSValueIsString(ctx, args[0])) {
185
		JSStringRef val_str = JSValueToStringCopy(ctx, args[0], NULL);
186
		char buf[1000];
187
		JSStringGetUTF8CString(val_str, buf, 1000);
188
189
		fprintf(stderr, "%s", buf);
190
		fflush(stderr);
191
	}
192
193
	return JSValueMakeNull(ctx);
194
}
195
54 196
JSValueRef function_import_script(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject,
55 197
		size_t argc, const JSValueRef args[], JSValueRef* exception) {
56 198
	if (argc == 1 && JSValueGetType(ctx, args[0]) == kJSTypeString) {
@ -95,7 +237,10 @@ int main(int argc, char **argv) {
95 237
96 238
	JSObjectRef global_obj = JSContextGetGlobalObject(ctx);
97 239
240
	evaluate_script(ctx, "var global = this;", "<init>");
241
98 242
	register_global_function(ctx, "IMPORT_SCRIPT", function_import_script);
243
	bootstrap(ctx, "out/main.js", "out/goog/base.js");
99 244
100 245
	register_global_function(ctx, "CONSOLE_LOG", function_console_log);
101 246
	register_global_function(ctx, "CONSOLE_ERROR", function_console_error);
@ -104,7 +249,54 @@ int main(int argc, char **argv) {
104 249
			"console.log = CONSOLE_LOG;"\
105 250
			"console.error = CONSOLE_ERROR;", "<init>");
106 251
107
	bootstrap(ctx, "out/main.js", "out/goog/base.js");
252
	// require app namespaces
253
	evaluate_script(ctx, "goog.require('planck.repl');", "<init>");
254
255
	// without this things won't work
256
	evaluate_script(ctx, "var window = global;", "<init>");
257
258
	register_global_function(ctx, "PLANCK_READ_FILE", function_read_file);
259
	register_global_function(ctx, "PLANCK_LOAD", function_load);
260
	register_global_function(ctx, "PLANCK_LOAD_DEPS_CLJS_FILES", function_load_deps_cljs_files);
261
262
	register_global_function(ctx, "PLANCK_EVAL", function_eval);
263
264
	register_global_function(ctx, "PLANCK_GET_TERM_SIZE", function_get_term_size);
265
	register_global_function(ctx, "PLANCK_PRINT_FN", function_print_fn);
266
	register_global_function(ctx, "PLANCK_PRINT_ERR_FN", function_print_err_fn);
267
268
	evaluate_script(ctx, "cljs.core.set_print_fn_BANG_.call(null,PLANCK_PRINT_FN);", "<init>");
269
	evaluate_script(ctx, "cljs.core.set_print_err_fn_BANG_.call(null,PLANCK_PRINT_ERR_FN);", "<init>");
270
271
	bool repl = true;
272
273
	{
274
		JSValueRef arguments[4];
275
		bool verbose = true, static_fns = true;
276
		arguments[0] = JSValueMakeBoolean(ctx, repl);
277
		arguments[1] = JSValueMakeBoolean(ctx, verbose);
278
		JSStringRef cache_path_str = JSStringCreateWithUTF8CString(".planck_cache");
279
		arguments[2] = JSValueMakeString(ctx, cache_path_str);
280
		arguments[3] = JSValueMakeBoolean(ctx, static_fns);
281
		JSValueRef ex = NULL;
282
		JSObjectCallAsFunction(ctx, get_function(ctx, "planck.repl", "init"), JSContextGetGlobalObject(ctx), 4, arguments, &ex);
283
		debug_print_value
284
	("planck.repl/init", ctx, ex);
285
	}
286
287
	if (repl) {
288
		evaluate_source(ctx, "text", "(require '[planck.repl :refer-macros [apropos dir find-doc doc source pst]])", true, "cljs.user");
289
	}
290
291
	evaluate_script(ctx, "goog.provide('cljs.user');", "<init>");
292
	evaluate_script(ctx, "goog.require('cljs.core');", "<init>");
293
294
	evaluate_script(ctx, "cljs.core._STAR_assert_STAR_ = true;", "<init>");
295
296
	//evaluate_source(ctx, "text", "(empty? \"\")", true, "cljs.user");
297
298
	printf("---\nrequire macros\n---\n");
299
	evaluate_source(ctx, "text", "(require-macros 'planck.repl 'planck.core 'planck.shell 'planck.from.io.aviso.ansi 'clojure.template 'cljs.spec 'cljs.spec.impl.gen 'cljs.test)", true, "cljs.user");
108 300
109 301
	char *script;
110 302
	if (argc == 0) {
@ -151,20 +343,82 @@ JSValueRef evaluate_script(JSContextRef ctx, char *script, char *source) {
151 343
		JSStringRelease(source_ref);
152 344
	}
153 345
154
#ifdef DEBUG
155
	if (ex != NULL) {
156
		JSStringRef ex_str = to_string(ctx, ex);
157
		char ex_buf[1000];
158
		ex_buf[0] = '\0';
159
		JSStringGetUTF8CString(ex_str, ex_buf, 1000);
160
		printf("eval %s: %s\n", source, ex_buf);
161
		JSStringRelease(ex_str);
162
	}
163
#endif
346
	debug_print_value
347
("evaluate_script", ctx, ex);
164 348
165 349
	return val;
166 350
}
167 351
352
JSValueRef get_value_on_object(JSContextRef ctx, JSObjectRef obj, char *name) {
353
	JSStringRef name_str = JSStringCreateWithUTF8CString(name);
354
	JSValueRef val = JSObjectGetProperty(ctx, obj, name_str, NULL);
355
	JSStringRelease(name_str);
356
	return val;
357
}
358
359
JSValueRef get_value(JSContextRef ctx, char *namespace, char *name) {
360
	JSValueRef ns_val = NULL;
361
362
	// printf("get_value: '%s'\n", namespace);
363
	int len = strlen(namespace) + 1;
364
	char *ns_tmp = malloc(len * sizeof(char));
365
	char **ns_tmp_start = &ns_tmp;
366
	strncpy(ns_tmp, namespace, len);
367
	char *ns_part = strtok(ns_tmp, ".");
368
	ns_tmp = NULL;
369
	while (ns_part != NULL) {
370
		char *munged_ns_part = munge(ns_part);
371
		if (ns_val) {
372
			ns_val = get_value_on_object(ctx, JSValueToObject(ctx, ns_val, NULL), munged_ns_part);
373
		} else {
374
			ns_val = get_value_on_object(ctx, JSContextGetGlobalObject(ctx), munged_ns_part);
375
		}
376
		free(munged_ns_part); // TODO: Use a fixed buffer for this?  (Which would restrict namespace part length...)
377
378
		ns_part = strtok(NULL, ".");
379
	}
380
	//free(ns_tmp);
381
382
	return get_value_on_object(ctx, JSValueToObject(ctx, ns_val, NULL), name);
383
}
384
385
JSObjectRef get_function(JSContextRef ctx, char *namespace, char *name) {
386
	JSValueRef val = get_value(ctx, namespace, name);
387
	assert(!JSValueIsUndefined(ctx, val));
388
	return JSValueToObject(ctx, val, NULL);
389
}
390
391
void evaluate_source(JSContextRef ctx, char *type, char *source, bool expression, char *set_ns) {
392
	JSValueRef args[7];
393
	int num_args = 7;
394
395
	{
396
		JSValueRef source_args[2];
397
		JSStringRef type_str = JSStringCreateWithUTF8CString(type);
398
		source_args[0] = JSValueMakeString(ctx, type_str);
399
		JSStringRef source_str = JSStringCreateWithUTF8CString(source);
400
		source_args[1] = JSValueMakeString(ctx, source_str);
401
		args[0] = JSObjectMakeArray(ctx, 2, source_args, NULL);
402
	}
403
404
	args[1] = JSValueMakeBoolean(ctx, expression);
405
	args[2] = JSValueMakeBoolean(ctx, false);
406
	args[3] = JSValueMakeBoolean(ctx, false);
407
	JSStringRef set_ns_str = JSStringCreateWithUTF8CString(set_ns);
408
	args[4] = JSValueMakeString(ctx, set_ns_str);
409
	JSStringRef theme_str = JSStringCreateWithUTF8CString("dumb");
410
	args[5] = JSValueMakeString(ctx, theme_str);
411
	args[6] = JSValueMakeNumber(ctx, 0);
412
413
	JSObjectRef execute_fn = get_function(ctx, "planck.repl", "execute");
414
	JSObjectRef global_obj = JSContextGetGlobalObject(ctx);
415
	JSValueRef ex = NULL;
416
	JSObjectCallAsFunction(ctx, execute_fn, global_obj, num_args, args, &ex);
417
418
	debug_print_value
419
("planck.repl/execute", ctx, ex);
420
}
421
168 422
char *munge(char *s) {
169 423
	int len = strlen(s);
170 424
	int new_len = 0;
@ -260,15 +514,21 @@ void bootstrap(JSContextRef ctx, char *deps_file_path, char *goog_base_path) {
260 514
}
261 515
262 516
char *get_contents(char *path) {
517
/*#ifdef DEBUG
518
	printf("get_contents(\"%s\")\n", path);
519
#endif*/
520
521
	char *err_prefix;
522
263 523
	FILE *f = fopen(path, "r");
264 524
	if (f == NULL) {
265
		perror("fopen");
525
		err_prefix = "fopen";
266 526
		goto err;
267 527
	}
268 528
269 529
	struct stat f_stat;
270 530
	if (fstat(fileno(f), &f_stat) < 0) {
271
		perror("fstat");
531
		err_prefix = "fstat";
272 532
		goto err;
273 533
	}
274 534
@ -277,18 +537,19 @@ char *get_contents(char *path) {
277 537
	fread(buf, f_stat.st_size, 1, f);
278 538
	buf[f_stat.st_size] = '\0';
279 539
	if (ferror(f)) {
280
		perror("fread");
540
		err_prefix = "fread";
281 541
		free(buf);
282 542
		goto err;
283 543
	}
284 544
285 545
	if (fclose(f) < 0) {
286
		perror("fclose");
546
		err_prefix = "fclose";
287 547
		goto err;
288 548
	}
289 549
290 550
	return buf;
291 551
292 552
err:
553
	printf("get_contents(\"%s\"): %s: %s\n", path, err_prefix, strerror(errno));
293 554
	return NULL;
294 555
}