1 
2 //--metadoc State copyright Steve Dekorte 2002
3 //--metadoc State license BSD revised
4 
5 #define IOSTATE_C 1
6 #include "IoState.h"
7 #undef IOSTATE_C
8 
9 #include "IoObject.h"
10 #include "IoCall.h"
11 #include "IoCoroutine.h"
12 #include "IoSeq.h"
13 #include "IoNumber.h"
14 #include "IoCFunction.h"
15 #include "IoBlock.h"
16 #include "IoList.h"
17 #include "IoMap.h"
18 //#include "IoRange.h"
19 #include "IoFile.h"
20 #include "IoDate.h"
21 #include "IoDuration.h"
22 #include "IoSeq.h"
23 #include "IoMessage_parser.h"
24 #include "IoDynLib.h"
25 #include "IoWeakLink.h"
26 #include "IoError.h"
27 
28 #include "IoSystem.h"
29 #include "IoCompiler.h"
30 #include "IoDebugger.h"
31 #include "IoCollector.h"
32 #include "IoSandbox.h"
33 #include "IoDirectory.h"
34 #include "IoProfiler.h"
35 //#include "IoEditLine.h"
36 
37 #include <stdlib.h>
38 
39 void IoVMCodeInit(IoObject *context);
40 
IoState_new_atAddress(void * address)41 void IoState_new_atAddress(void *address)
42 {
43 	IoState *self = (IoState *)address;
44 	IoCFunction *cFunctionProto;
45 	IoSeq *seqProto;
46 
47 	self->randomGen = RandomGen_new();
48 	RandomGen_setSeed(self->randomGen, 754905204); // no particular reason for this seed
49 	// collector
50 
51 	self->collector = Collector_new();
52 	IoState_pushCollectorPause(self);
53 
54 	Collector_setMarkFunc_(self->collector, (CollectorMarkFunc *)IoObject_mark);
55 	Collector_setWillFreeFunc_(self->collector, (CollectorWillFreeFunc *)IoObject_willFree);
56 	Collector_setFreeFunc_(self->collector, (CollectorFreeFunc *)IoObject_free);
57 
58 	self->mainArgs   = MainArgs_new();
59 	self->primitives = PointerHash_new();
60 
61 	self->recycledObjects = List_new();
62 	self->maxRecycledObjects = IOSTATE_DEFAULT_MAX_RECYCLED_OBJECTS;
63 
64 	// Sandbox
65 
66 	self->messageCount = 0;
67 	self->messageCountLimit = 0;
68 	self->endTime = 0;
69 
70 	// symbol table
71 
72 	self->symbols = CHash_new();
73 
74 	CHash_setEqualFunc_(self->symbols, (CHashEqualFunc *)UArray_equals_);
75 	CHash_setHash1Func_(self->symbols, (CHashHashFunc *)UArray_evenHash);
76 	CHash_setHash2Func_(self->symbols, (CHashHashFunc *)UArray_oddHash);
77 
78 	/*
79 	Problem:
80 	- there are some interdependencies here:
81 	- creating instances requires a retain stack
82 	- we need a Coroutine to use for our retainStack
83 	- defining any primitive methods requires Strings and CFunctions
84 
85 	Solution:
86 	- create a temporary fake stack
87 	- create Object, CFunction and String protos sans methods.
88 	- then add methods to Object, CFunction and String
89 	*/
90 
91 	self->currentIoStack = Stack_new(); // temp retain stack until coro is up
92 
93 	self->objectProto = IoObject_proto(self); // need to do this first, so we have a retain stack
94 	//IoState_retain_(self, self->objectProto);
95 
96 	self->mainCoroutine = IoCoroutine_proto(self);
97 	Stack_free(self->currentIoStack);
98 	self->currentIoStack = NULL;
99 
100 	IoState_setCurrentCoroutine_(self, self->mainCoroutine);
101 
102 	seqProto = IoSeq_proto(self);
103 
104 	IoState_setupQuickAccessSymbols(self);
105 
106 	IoObject_rawSetProto_(seqProto, self->objectProto);
107 
108 	cFunctionProto = IoCFunction_proto(self);
109 	self->localsUpdateSlotCFunc = IoState_retain_(self,
110 												  IoCFunction_newWithFunctionPointer_tag_name_(self,
111 												  IoObject_localsUpdateSlot, NULL, "localsUpdate"));
112 
113 	IoSeq_protoFinish(seqProto);
114 	IoObject_protoFinish(self);
115 	IoCFunction_protoFinish(self);
116 	IoCoroutine_protoFinish(self->mainCoroutine);
117 
118 	self->setSlotBlock  = IoState_retain_(self, IoObject_getSlot_(self->objectProto, SIOSYMBOL("setSlot")));
119 
120 	// setup lobby
121 
122 	{
123 		IoObject *objectProto = self->objectProto;
124 		IoObject *protos = IOCLONE(objectProto);
125 		IoObject *core = IOCLONE(objectProto);
126 
127 		self->core = core;
128 		self->lobby = IOCLONE(objectProto);
129 		IoState_retain_(self, self->lobby);
130 		IoState_retain_(self, self->core);
131 
132 		// setup namespace
133 
134 		IoObject_setSlot_to_(self->lobby, SIOSYMBOL("Lobby"), self->lobby);
135 		IoObject_setSlot_to_(self->lobby, SIOSYMBOL("Protos"), protos);
136 		IoObject_setSlot_to_(protos, SIOSYMBOL("Core"), core);
137 		IoObject_setSlot_to_(protos, SIOSYMBOL("Addons"), IOCLONE(objectProto));
138 
139 		IoObject_setSlot_to_(core, SIOSYMBOL("Compiler"),  IoCompiler_proto(self));
140 		IoObject_setSlot_to_(core, SIOSYMBOL("Collector"), IoCollector_proto(self));
141 		IoObject_setSlot_to_(core, SIOSYMBOL("Exception"), IOCLONE(objectProto));
142 
143 		// setup proto chain
144 
145 		IoObject_rawSetProto_(objectProto, self->lobby);
146 		IoObject_rawSetProto_(self->lobby, protos);
147 		IoObject_rawSetProto_(protos, core);
148 
149 		// add protos to namespace
150 
151 		IoObject_setSlot_to_(core, SIOSYMBOL("Object"), objectProto);
152 		IoObject_setSlot_to_(core, SIOSYMBOL("Sequence"), seqProto);
153 		IoObject_setSlot_to_(core, SIOSYMBOL("Number"), IoNumber_proto(self));
154 
155 		IoState_setupCachedNumbers(self);
156 
157 		{
158 			IoObject *systemProto = IoSystem_proto(self);
159 			IoObject_setSlot_to_(core, SIOSYMBOL("System"), systemProto);
160 		}
161 
162 		IoState_setupSingletons(self);
163 		IoState_setupCachedMessages(self);
164 
165 		{
166 			self->debugger = IoState_retain_(self, IoDebugger_proto(self));
167 			IoObject_setSlot_to_(core, SIOSYMBOL("Debugger"), self->debugger);
168 
169 			self->vmWillSendMessage  = IoMessage_newWithName_(self, SIOSYMBOL("vmWillSendMessage"));
170 			IoMessage_rawSetCachedResult_(self->nilMessage, self->ioNil);
171 			IoState_retain_(self, self->vmWillSendMessage);
172 		}
173 
174 		IoObject_setSlot_to_(core, SIOSYMBOL("Block"),      IoBlock_proto(self));
175 		IoObject_setSlot_to_(core, SIOSYMBOL("List"),       IoList_proto(self));
176 		IoObject_setSlot_to_(core, SIOSYMBOL("Map"),        IoMap_proto(self));
177 		//IoObject_setSlot_to_(core, SIOSYMBOL("Range"),      IoRange_proto(self));
178 		IoObject_setSlot_to_(core, SIOSYMBOL("Coroutine"),  self->mainCoroutine);
179 		IoObject_setSlot_to_(core, SIOSYMBOL("Error"),      IoError_proto(self));
180 		IoObject_setSlot_to_(core, SIOSYMBOL("File"),       IoFile_proto(self));
181 		IoObject_setSlot_to_(core, SIOSYMBOL("Directory"),  IoDirectory_proto(self));
182 		IoObject_setSlot_to_(core, SIOSYMBOL("Date"),       IoDate_proto(self));
183 		IoObject_setSlot_to_(core, SIOSYMBOL("Duration"),   IoDuration_proto(self));
184 		IoObject_setSlot_to_(core, SIOSYMBOL("WeakLink"),   IoWeakLink_proto(self));
185 		IoObject_setSlot_to_(core, SIOSYMBOL("Sandbox"),    IoSandbox_proto(self));
186 		//IoObject_setSlot_to_(core, SIOSYMBOL("EditLine"),   IoEditLine_proto(self));
187 
188 #if !defined(__SYMBIAN32__)
189 		IoObject_setSlot_to_(core, SIOSYMBOL("DynLib"),     IoDynLib_proto(self));
190 #endif
191 
192 		//self->store =
193 		//IoObject_setSlot_to_(core, SIOSYMBOL("Store"),      self->store);
194 		IoObject_setSlot_to_(core, SIOSYMBOL("CFunction"),  cFunctionProto);
195 		IoObject_setSlot_to_(core, SIOSYMBOL("Profiler"),  IoProfiler_proto(self));
196 
197 		self->localsProto = IoState_retain_(self, IoObject_localsProto(self));
198 		IoObject_setSlot_to_(core, SIOSYMBOL("Locals"),  self->localsProto);
199 
200 		self->stopStatus = MESSAGE_STOP_STATUS_NORMAL;
201 		self->returnValue = self->ioNil;
202 
203 		IoState_clearRetainStack(self);
204 
205 		IoState_popCollectorPause(self);
206 
207 		//Collector_collect(self->collector);
208 
209 		//io_show_mem("before IoVMCodeInit");
210 		IoVMCodeInit(core);
211 
212 		//io_show_mem("after IoVMCodeInit");
213 		//Collector_collect(self->collector);
214 		//io_show_mem("after Collector_collect");
215 
216 		//IoState_popCollectorPause(self);
217 		IoState_clearRetainStack(self);
218 
219 		//Collector_check(self->collector);
220 		Collector_collect(self->collector);
221 		//io_show_mem("after IoState_clearRetainStack and Collector_collect");
222 		IoState_setupUserInterruptHandler(self);
223 	}
224 }
225 
IoState_new(void)226 IoState *IoState_new(void)
227 {
228 	IoState *self = (IoState *)io_calloc(1, sizeof(IoState));
229 	IoState_new_atAddress(self);
230 	return self;
231 }
232 
IoState_retainedSymbol(IoState * self,char * s)233 IoSymbol *IoState_retainedSymbol(IoState *self, char *s)
234 {
235 	return IoState_retain_(self, SIOSYMBOL(s));
236 }
237 
238 
IoState_setupQuickAccessSymbols(IoState * self)239 void IoState_setupQuickAccessSymbols(IoState *self)
240 {
241 	self->activateSymbol     = IoState_retainedSymbol(self, "activate");
242 	self->callSymbol         = IoState_retainedSymbol(self, "call");
243 	self->forwardSymbol      = IoState_retainedSymbol(self, "forward");
244 	self->noShufflingSymbol  = IoState_retainedSymbol(self, "__noShuffling__");
245 	self->opShuffleSymbol    = IoState_retainedSymbol(self, "opShuffle");
246 	//self->performSymbol    = IoState_retainedSymbol(self, "perform");
247 	//self->referenceIdSymbol    = IoState_retainedSymbol(self, "referenceId");
248 	self->semicolonSymbol    = IoState_retainedSymbol(self, ";");
249 	self->selfSymbol         = IoState_retainedSymbol(self, "self");
250 	self->setSlotSymbol      = IoState_retainedSymbol(self, "setSlot");
251 	self->setSlotWithTypeSymbol  = IoState_retainedSymbol(self, "setSlotWithType");
252 	self->stackSizeSymbol    = IoState_retainedSymbol(self, "stackSize");
253 	self->typeSymbol         = IoState_retainedSymbol(self, "type");
254 	self->updateSlotSymbol   = IoState_retainedSymbol(self, "updateSlot");
255 	self->runTargetSymbol   = IoState_retainedSymbol(self, "runTarget");
256 	self->runMessageSymbol   = IoState_retainedSymbol(self, "runMessage");
257 	self->runLocalsSymbol   = IoState_retainedSymbol(self, "runLocals");
258 	self->parentCoroutineSymbol   = IoState_retainedSymbol(self, "parentCoroutine");
259 	self->resultSymbol   = IoState_retainedSymbol(self, "result");
260 	self->exceptionSymbol   = IoState_retainedSymbol(self, "exception");
261 }
262 
IoState_setupSingletons(IoState * self)263 void IoState_setupSingletons(IoState *self)
264 {
265 	IoObject *core = self->core;
266 	// nil
267 
268 	self->ioNil = IOCLONE(self->objectProto);
269 	IoObject_setSlot_to_(core, SIOSYMBOL("nil"), self->ioNil);
270 	//IoObject_setSlot_to_(core, self->noShufflingSymbol, self->ioNil);
271 	IoObject_setSlot_to_(core, SIOSYMBOL("Message"), IoMessage_proto(self));
272 	IoObject_setSlot_to_(core, SIOSYMBOL("Call"),  IoCall_proto(self));
273 
274 	self->nilMessage  = IoMessage_newWithName_(self, SIOSYMBOL("nil"));
275 	IoMessage_rawSetCachedResult_(self->nilMessage, self->ioNil);
276 	IoState_retain_(self, self->nilMessage);
277 
278 	// true
279 
280 	self->ioTrue = IoObject_new(self);
281 	IoObject_setSlot_to_(core, SIOSYMBOL("true"), self->ioTrue);
282 	IoObject_setSlot_to_(self->ioTrue, SIOSYMBOL("type"), SIOSYMBOL("true"));
283 	IoState_retain_(self, self->ioTrue);
284 
285 	// false
286 
287 	self->ioFalse = IoObject_new(self);
288 	IoObject_setSlot_to_(core, SIOSYMBOL("false"), self->ioFalse);
289 	IoObject_setSlot_to_(self->ioFalse, SIOSYMBOL("type"), SIOSYMBOL("false"));
290 	IoState_retain_(self, self->ioFalse);
291 
292 	// Flow control: Normal
293 	self->ioNormal = IoObject_new(self);
294 	IoObject_setSlot_to_(core, SIOSYMBOL("Normal"), self->ioNormal);
295 	IoObject_setSlot_to_(self->ioNormal, SIOSYMBOL("type"), SIOSYMBOL("Normal"));
296 	IoState_retain_(self, self->ioNormal);
297 
298 	// Flow control: Break
299 	self->ioBreak = IoObject_new(self);
300 	IoObject_setSlot_to_(core, SIOSYMBOL("Break"), self->ioBreak);
301 	IoObject_setSlot_to_(self->ioBreak, SIOSYMBOL("type"), SIOSYMBOL("Break"));
302 	IoState_retain_(self, self->ioBreak);
303 
304 	// Flow control: Continue
305 	self->ioContinue = IoObject_new(self);
306 	IoObject_setSlot_to_(core, SIOSYMBOL("Continue"), self->ioContinue);
307 	IoObject_setSlot_to_(self->ioContinue, SIOSYMBOL("type"), SIOSYMBOL("Continue"));
308 	IoState_retain_(self, self->ioContinue);
309 
310 	// Flow control: Return
311 	self->ioReturn = IoObject_new(self);
312 	IoObject_setSlot_to_(core, SIOSYMBOL("Return"), self->ioReturn);
313 	IoObject_setSlot_to_(self->ioReturn, SIOSYMBOL("type"), SIOSYMBOL("Return"));
314 	IoState_retain_(self, self->ioReturn);
315 
316 	// Flow control: Eol
317 	self->ioEol = IoObject_new(self);
318 	IoObject_setSlot_to_(core, SIOSYMBOL("Eol"), self->ioEol);
319 	IoObject_setSlot_to_(self->ioEol, SIOSYMBOL("type"), SIOSYMBOL("Eol"));
320 	IoState_retain_(self, self->ioEol);
321 }
322 
IoState_setupCachedMessages(IoState * self)323 void IoState_setupCachedMessages(IoState *self)
324 {
325 	self->asStringMessage = IoMessage_newWithName_(self, SIOSYMBOL("asString"));
326 	IoState_retain_(self, self->asStringMessage);
327 
328 	self->collectedLinkMessage = IoMessage_newWithName_(self, SIOSYMBOL("collectedLink"));
329 	IoState_retain_(self, self->collectedLinkMessage);
330 
331 	self->compareMessage = IoMessage_newWithName_(self, SIOSYMBOL("compare"));
332 	IoState_retain_(self, self->compareMessage);
333 
334 	//self->doStringMessage = IoMessage_newWithName_(self, SIOSYMBOL("doString"));
335 	//IoState_retain_(self, self->doStringMessage);
336 
337 	self->initMessage = IoMessage_newWithName_(self, SIOSYMBOL("init"));
338 	IoState_retain_(self, self->initMessage);
339 
340 	self->mainMessage = IoMessage_newWithName_(self, SIOSYMBOL("main"));
341 	IoState_retain_(self, self->mainMessage);
342 
343 	self->opShuffleMessage = IoMessage_newWithName_(self, self->opShuffleSymbol);
344 	IoState_retain_(self, self->opShuffleMessage);
345 
346 	self->printMessage = IoMessage_newWithName_(self, SIOSYMBOL("print"));
347 	IoState_retain_(self, self->printMessage);
348 
349 	self->referenceIdForObjectMessage = IoMessage_newWithName_(self, SIOSYMBOL("referenceIdForObject"));
350 	IoState_retain_(self, self->referenceIdForObjectMessage);
351 
352 	self->objectForReferenceIdMessage = IoMessage_newWithName_(self, SIOSYMBOL("objectForReferenceId"));
353 	IoState_retain_(self, self->objectForReferenceIdMessage);
354 
355 	self->runMessage = IoMessage_newWithName_(self, SIOSYMBOL("run"));
356 	IoState_retain_(self, self->runMessage);
357 
358 	self->willFreeMessage = IoMessage_newWithName_(self, SIOSYMBOL("willFree"));
359 	IoState_retain_(self, self->willFreeMessage);
360 
361 	self->yieldMessage = IoMessage_newWithName_(self, SIOSYMBOL("yield"));
362 	IoState_retain_(self, self->yieldMessage);
363 
364 	self->didFinishMessage = IoMessage_newWithName_(self, SIOSYMBOL("didFinish"));
365 	IoState_retain_(self, self->didFinishMessage);
366 
367 	self->asBooleanMessage = IoMessage_newWithName_(self, SIOSYMBOL("asBoolean"));
368 	IoState_retain_(self, self->asBooleanMessage);
369 }
370 
IO_METHOD(IoObject,initBindings)371 IO_METHOD(IoObject, initBindings)
372 {
373 	IOSTATE->bindingsInitCallback(IOSTATE, self);
374 	return self;
375 }
376 
IoState_init(IoState * self)377 void IoState_init(IoState *self)
378 {
379 	if (self->bindingsInitCallback)
380 	{
381 		IoState_pushCollectorPause(self);
382 		self->bindingsInitCallback(self, self->core);
383 		IoState_popCollectorPause(self);
384 		IoState_clearRetainStack(self);
385 	}
386 }
387 
388 /*
389 IoObject_registerAsProto(IoObject *self)
390 {
391 	IoState_registerProtoWithNamed_(IOSTATE, self, IoObject_name(self));
392 }
393 
394 void IoState_registerProtoWithNamed_(IoState *self, IoObject *proto, const char *name)
395 {
396 	if (PointerHash_at_(self->primitives, (void *)name))
397 	{
398 		printf("Error registering proto: %s\n", IoObject_name(proto));
399 		IoState_fatalError_(self, "IoState_registerProtoWithFunc_() Error: attempt to add the same proto twice");
400 	}
401 
402 	IoState_retain_(self, proto);
403 	PointerHash_at_put_(self->primitives, (void *)func, proto);
404 	//printf("registered %s\n", IoObject_name(proto));
405 }
406 */
407 
IoState_registerProtoWithFunc_(IoState * self,IoObject * proto,const char * v)408 void IoState_registerProtoWithFunc_(IoState *self, IoObject *proto, const char *v)
409 {
410 	IoState_registerProtoWithId_(self, proto, v);
411 }
412 
IoState_registerProtoWithId_(IoState * self,IoObject * proto,const char * v)413 IOVM_API void IoState_registerProtoWithId_(IoState *self, IoObject *proto, const char *v)
414 {
415 	if (PointerHash_at_(self->primitives, (void *)v))
416 	{
417 		printf("Error registering proto: %s\n", IoObject_name(proto));
418 		IoState_fatalError_(self, "IoState_registerProtoWithFunc_() Error: attempt to add the same proto twice");
419 	}
420 
421 	IoState_retain_(self, proto);
422 	PointerHash_at_put_(self->primitives, (void *)v, proto);
423 	//printf("registered %s\n", IoObject_name(proto));
424 }
425 
IoState_protoWithName_(IoState * self,const char * name)426 IoObject *IoState_protoWithName_(IoState *self, const char *name)
427 {
428 	POINTERHASH_FOREACH(self->primitives, key, proto, if (!strcmp(IoObject_name(proto), name)) { return proto; });
429 	return NULL;
430 }
431 
IoState_tagList(IoState * self)432 List *IoState_tagList(IoState *self) // caller must io_free returned List
433 {
434 	List *tags = List_new();
435 	POINTERHASH_FOREACH(self->primitives, k, proto, List_append_(tags, IoObject_tag((IoObject *)proto)));
436 	return tags;
437 }
438 
IoState_done(IoState * self)439 void IoState_done(IoState *self)
440 {
441 	// this should only be called from the main coro from outside of Io
442 
443 	List *tags = IoState_tagList(self); // need to get the tags before we io_free the protos
444 
445 	self->maxRecycledObjects = 0;
446 
447 	Collector_freeAllValues(self->collector); // io_free all objects known to the collector
448 	Collector_free(self->collector);
449 
450 	List_do_(tags, (ListDoCallback *)IoTag_free);
451 	List_free(tags);
452 
453 	PointerHash_free(self->primitives);
454 	CHash_free(self->symbols);
455 
456 	LIST_DO_(self->recycledObjects, IoObject_dealloc); // this does not work now that objects and marks are separate
457 	List_free(self->recycledObjects);
458 	List_free(self->cachedNumbers);
459 
460 	RandomGen_free(self->randomGen);
461 	MainArgs_free(self->mainArgs);
462 }
463 
IoState_free(IoState * self)464 void IoState_free(IoState *self)
465 {
466 	IoState_done(self);
467 	io_free(self);
468 }
469 
IoState_lobby(IoState * self)470 IoObject *IoState_lobby(IoState *self)
471 {
472 	return self->lobby;
473 }
474 
IoState_setLobby_(IoState * self,IoObject * obj)475 void IoState_setLobby_(IoState *self, IoObject *obj)
476 {
477 	self->lobby = obj;
478 }
479 
MissingProtoError(void)480 void MissingProtoError(void)
481 {
482 	printf("missing proto\n");
483 }
484 
IoState_protoWithId_(IoState * self,const char * v)485 IoObject *IoState_protoWithId_(IoState *self, const char *v)
486 {
487 	IoObject *proto = PointerHash_at_(self->primitives, (void *)v);
488 
489 	//printf("IoState_protoWithId_(self, %s)\n", v);
490 
491 	if (!proto)
492 	{
493 		printf("IoState fatal error: missing proto '%s'", v);
494 		IoState_fatalError_(self, "IoState_protoWithId_() Error: missing proto with id");
495 	}
496 
497 	return proto;
498 }
499 
500 
501 // command line ------------------------------------------------
502 
IoState_argc_argv_(IoState * self,int argc,const char * argv[])503 void IoState_argc_argv_(IoState *self, int argc, const char *argv[])
504 {
505 	IoList *args = IoList_new(self);
506 	int i;
507 
508 	for (i = 1; i < argc; i ++)
509 	{
510 		IoList_rawAppend_(args, SIOSYMBOL(argv[i]));
511 	}
512 
513 	{
514 		IoObject *system = IoObject_getSlot_(self->lobby, SIOSYMBOL("System"));
515 		IoObject_setSlot_to_(system, SIOSYMBOL("args"), args);
516 	}
517 
518 	MainArgs_argc_argv_(self->mainArgs, argc, argv);
519 }
520 
521 // store -------------------------------------------------------
522 
IoState_objectWithPid_(IoState * self,PID_TYPE pid)523 IoObject *IoState_objectWithPid_(IoState *self, PID_TYPE pid)
524 {
525 	return self->ioNil;
526 }
527 
528 // doString -------------------------------------------------------
529 
IoState_rawOn_doCString_withLabel_(IoState * self,IoObject * target,const char * s,const char * label)530 IoObject *IoState_rawOn_doCString_withLabel_(IoState *self,
531 									IoObject *target,
532 									const char *s,
533 									const char *label)
534 {
535 	IoMessage *m = IoMessage_newFromText_label_(self, s, label);
536 	return IoMessage_locals_performOn_(m, target, target);
537 }
538 
539 // CLI ---------------------------------------------------------
540 
IoState_rawPrompt(IoState * self)541 void IoState_rawPrompt(IoState *self)
542 {
543 	int max = 1024 * 16;
544 	char *s = io_calloc(1, max);
545 	IoObject *result;
546 
547 	for (;;)
548 	{
549 		fputs("Io> ", stdout);
550 		fflush(stdout);
551 		fgets(s, max, stdin);
552 
553 		if (feof(stdin))
554 		{
555 			break;
556 		}
557 
558 		result = IoState_rawOn_doCString_withLabel_(self, self->lobby, s, "IoState_rawPrompt()");
559 
560 		fputs("==> ", stdout);
561 		IoObject_print(result);
562 		fputs("\n", stdout);
563 	}
564 
565 	io_free(s);
566 }
567 
IoState_runCLI(IoState * self)568 void IoState_runCLI(IoState *self)
569 {
570 	IoObject *result = IoState_on_doCString_withLabel_(self, self->lobby, "CLI run", "IoState_runCLI()");
571 	IoObject *e = IoCoroutine_rawException(self->currentCoroutine);
572 
573 	if (e != self->ioNil)
574 	{
575 		self->exitResult = -1;
576 	}
577 	else if (!self->shouldExit && ISNUMBER(result))
578 	{
579 		self->exitResult = CNUMBER(result);
580 	}
581 }
582 
IoState_exitResult(IoState * self)583 IOVM_API int IoState_exitResult(IoState *self)
584 {
585 	return self->exitResult;
586 }
587 
588 
589