Просмотр исходного кода

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
Родитель
Сommit
97e800fa5f
1 измененных файлов с 276 добавлено и 15 удалено
  1. 276 15
      c/ton/main.c

+ 276 - 15
c/ton/main.c

1
#include <assert.h>
2
#include <errno.h>
1
#include <stdio.h>
3
#include <stdio.h>
2
#include <stdlib.h>
4
#include <stdlib.h>
3
#include <string.h>
5
#include <string.h>
13
JSStringRef to_string(JSContextRef ctx, JSValueRef val);
15
JSStringRef to_string(JSContextRef ctx, JSValueRef val);
14
JSValueRef evaluate_script(JSContextRef ctx, char *script, char *source);
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
char *munge(char *s);
19
char *munge(char *s);
17
20
18
void bootstrap(JSContextRef ctx, char *deps_file_path, char *goog_base_path);
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
char* get_contents(char *path);
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
JSValueRef function_console_log(JSContextRef ctx, JSObjectRef function, JSObjectRef this_object,
39
JSValueRef function_console_log(JSContextRef ctx, JSObjectRef function, JSObjectRef this_object,
23
		size_t argc, const JSValueRef args[], JSValueRef* exception) {
40
		size_t argc, const JSValueRef args[], JSValueRef* exception) {
24
	for (int i = 0; i < argc; i++) {
41
	for (int i = 0; i < argc; i++) {
51
	return JSValueMakeUndefined(ctx);
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
JSValueRef function_import_script(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject,
196
JSValueRef function_import_script(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject,
55
		size_t argc, const JSValueRef args[], JSValueRef* exception) {
197
		size_t argc, const JSValueRef args[], JSValueRef* exception) {
56
	if (argc == 1 && JSValueGetType(ctx, args[0]) == kJSTypeString) {
198
	if (argc == 1 && JSValueGetType(ctx, args[0]) == kJSTypeString) {
95
237
96
	JSObjectRef global_obj = JSContextGetGlobalObject(ctx);
238
	JSObjectRef global_obj = JSContextGetGlobalObject(ctx);
97
239
240
	evaluate_script(ctx, "var global = this;", "<init>");
241
98
	register_global_function(ctx, "IMPORT_SCRIPT", function_import_script);
242
	register_global_function(ctx, "IMPORT_SCRIPT", function_import_script);
243
	bootstrap(ctx, "out/main.js", "out/goog/base.js");
99
244
100
	register_global_function(ctx, "CONSOLE_LOG", function_console_log);
245
	register_global_function(ctx, "CONSOLE_LOG", function_console_log);
101
	register_global_function(ctx, "CONSOLE_ERROR", function_console_error);
246
	register_global_function(ctx, "CONSOLE_ERROR", function_console_error);
104
			"console.log = CONSOLE_LOG;"\
249
			"console.log = CONSOLE_LOG;"\
105
			"console.error = CONSOLE_ERROR;", "<init>");
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
	char *script;
301
	char *script;
110
	if (argc == 0) {
302
	if (argc == 0) {
151
		JSStringRelease(source_ref);
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
	return val;
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
char *munge(char *s) {
422
char *munge(char *s) {
169
	int len = strlen(s);
423
	int len = strlen(s);
170
	int new_len = 0;
424
	int new_len = 0;
260
}
514
}
261
515
262
char *get_contents(char *path) {
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
	FILE *f = fopen(path, "r");
523
	FILE *f = fopen(path, "r");
264
	if (f == NULL) {
524
	if (f == NULL) {
265
		perror("fopen");
525
		err_prefix = "fopen";
266
		goto err;
526
		goto err;
267
	}
527
	}
268
528
269
	struct stat f_stat;
529
	struct stat f_stat;
270
	if (fstat(fileno(f), &f_stat) < 0) {
530
	if (fstat(fileno(f), &f_stat) < 0) {
271
		perror("fstat");
531
		err_prefix = "fstat";
272
		goto err;
532
		goto err;
273
	}
533
	}
274
534
277
	fread(buf, f_stat.st_size, 1, f);
537
	fread(buf, f_stat.st_size, 1, f);
278
	buf[f_stat.st_size] = '\0';
538
	buf[f_stat.st_size] = '\0';
279
	if (ferror(f)) {
539
	if (ferror(f)) {
280
		perror("fread");
540
		err_prefix = "fread";
281
		free(buf);
541
		free(buf);
282
		goto err;
542
		goto err;
283
	}
543
	}
284
544
285
	if (fclose(f) < 0) {
545
	if (fclose(f) < 0) {
286
		perror("fclose");
546
		err_prefix = "fclose";
287
		goto err;
547
		goto err;
288
	}
548
	}
289
549
290
	return buf;
550
	return buf;
291
551
292
err:
552
err:
553
	printf("get_contents(\"%s\"): %s: %s\n", path, err_prefix, strerror(errno));
293
	return NULL;
554
	return NULL;
294
}
555
}