Fixed a lazySlot bug where lazy slots in different objects end up pointing to the...
[io/quag.git] / libs / iovm / source / IoState.c
blob8db886bfaec9dbf837c533a3a140ba766fc9ef0e
1 /*
2 docCopyright("Steve Dekorte", 2002)
3 docLicense("BSD revised")
4 */
6 #define IOSTATE_C 1
7 #include "IoState.h"
8 #undef IOSTATE_C
10 #include "IoObject.h"
11 #include "IoCall.h"
12 #include "IoCoroutine.h"
13 #include "IoSeq.h"
14 #include "IoNumber.h"
15 #include "IoCFunction.h"
16 #include "IoBlock.h"
17 #include "IoList.h"
18 #include "IoMap.h"
19 //#include "IoRange.h"
20 #include "IoFile.h"
21 #include "IoDate.h"
22 #include "IoDuration.h"
23 #include "IoSeq.h"
24 #include "IoMessage_parser.h"
25 #include "IoDynLib.h"
26 #include "IoWeakLink.h"
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 "IoEditLine.h"
36 #include <stdlib.h>
38 void IoVMCodeInit(IoObject *context);
40 void IoState_new_atAddress(void *address)
42 IoState *self = (IoState *)address;
43 IoCFunction *cFunctionProto;
44 IoSeq *seqProto;
46 // collector
48 self->collector = Collector_new();
49 IoState_pushCollectorPause(self);
51 Collector_setMarkFunc_(self->collector, (CollectorMarkFunc *)IoObject_mark);
52 Collector_setWillFreeFunc_(self->collector, (CollectorWillFreeFunc *)IoObject_willFree);
53 Collector_setFreeFunc_(self->collector, (CollectorFreeFunc *)IoObject_free);
55 self->mainArgs = MainArgs_new();
56 self->primitives = PHash_new();
58 self->recycledObjects = List_new();
59 self->maxRecycledObjects = IOSTATE_DEFAULT_MAX_RECYCLED_OBJECTS;
61 // Sandbox
63 self->messageCount = 0;
64 self->messageCountLimit = 0;
65 self->endTime = 0;
67 // symbol table
69 self->symbols = SHash_new();
71 SHash_setKeysEqualCallback(self->symbols, (SHashKeysEqualCallback *)UArray_equalsWithHashCheck_);
72 SHash_setHashForKeyCallback(self->symbols, (SHashHashforKeyCallback *)UArray_hash);
75 Problem:
76 - there are some interdependencies here:
77 - creating instances requires a retain stack
78 - we need a Coroutine to use for our retainStack
79 - defining any primitive methods requires Strings and CFunctions
81 Solution:
82 - create a temporary fake stack
83 - create Object, CFunction and String protos sans methods.
84 - then add methods to Object, CFunction and String
87 self->currentIoStack = Stack_new(); // temp retain stack until coro is up
89 self->objectProto = IoObject_proto(self); // need to do this first, so we have a retain stack
90 //IoState_retain_(self, self->objectProto);
92 self->mainCoroutine = IoCoroutine_proto(self);
93 Stack_free(self->currentIoStack);
94 self->currentIoStack = NULL;
96 IoState_setCurrentCoroutine_(self, self->mainCoroutine);
98 seqProto = IoSeq_proto(self);
100 IoState_setupQuickAccessSymbols(self);
102 IoObject_rawSetProto_(seqProto, self->objectProto);
104 cFunctionProto = IoCFunction_proto(self);
105 self->localsUpdateSlotCFunc = IoState_retain_(self,
106 IoCFunction_newWithFunctionPointer_tag_name_(self,
107 IoObject_localsUpdateSlot, NULL, "localsUpdate"));
109 IoSeq_protoFinish(seqProto);
110 IoObject_protoFinish(self);
111 IoCFunction_protoFinish(self);
112 IoCoroutine_protoFinish(self->mainCoroutine);
114 self->setSlotBlock = IoState_retain_(self, IoObject_getSlot_(self->objectProto, SIOSYMBOL("setSlot")));
116 // setup lobby
119 IoObject *objectProto = self->objectProto;
120 IoObject *protos = IOCLONE(objectProto);
121 IoObject *core = IOCLONE(objectProto);
123 self->core = core;
124 self->lobby = IOCLONE(objectProto);
125 IoState_retain_(self, self->lobby);
126 IoState_retain_(self, self->core);
128 // setup namespace
130 IoObject_setSlot_to_(self->lobby, SIOSYMBOL("Lobby"), self->lobby);
131 IoObject_setSlot_to_(self->lobby, SIOSYMBOL("Protos"), protos);
132 IoObject_setSlot_to_(protos, SIOSYMBOL("Core"), core);
133 IoObject_setSlot_to_(protos, SIOSYMBOL("Addons"), IOCLONE(objectProto));
135 IoObject_setSlot_to_(core, SIOSYMBOL("Compiler"), IoCompiler_proto(self));
136 IoObject_setSlot_to_(core, SIOSYMBOL("Collector"), IoCollector_proto(self));
137 IoObject_setSlot_to_(core, SIOSYMBOL("Exception"), IOCLONE(objectProto));
139 // setup proto chain
141 IoObject_rawSetProto_(objectProto, self->lobby);
142 IoObject_rawSetProto_(self->lobby, protos);
143 IoObject_rawSetProto_(protos, core);
145 // add protos to namespace
147 IoObject_setSlot_to_(core, SIOSYMBOL("Object"), objectProto);
148 IoObject_setSlot_to_(core, SIOSYMBOL("Sequence"), seqProto);
149 IoObject_setSlot_to_(core, SIOSYMBOL("Number"), IoNumber_proto(self));
151 IoState_setupCachedNumbers(self);
154 IoObject *systemProto = IoSystem_proto(self);
155 IoObject_setSlot_to_(core, SIOSYMBOL("System"), systemProto);
158 IoState_setupSingletons(self);
159 IoState_setupCachedMessages(self);
162 self->debugger = IoState_retain_(self, IoDebugger_proto(self));
163 IoObject_setSlot_to_(core, SIOSYMBOL("Debugger"), self->debugger);
165 self->vmWillSendMessage = IoMessage_newWithName_(self, SIOSYMBOL("vmWillSendMessage"));
166 IoMessage_cachedResult_(self->nilMessage, self->ioNil);
167 IoState_retain_(self, self->vmWillSendMessage);
170 IoObject_setSlot_to_(core, SIOSYMBOL("Block"), IoBlock_proto(self));
171 IoObject_setSlot_to_(core, SIOSYMBOL("List"), IoList_proto(self));
172 IoObject_setSlot_to_(core, SIOSYMBOL("Map"), IoMap_proto(self));
173 //IoObject_setSlot_to_(core, SIOSYMBOL("Range"), IoRange_proto(self));
174 IoObject_setSlot_to_(core, SIOSYMBOL("Coroutine"), self->mainCoroutine);
175 IoObject_setSlot_to_(core, SIOSYMBOL("File"), IoFile_proto(self));
176 IoObject_setSlot_to_(core, SIOSYMBOL("Directory"), IoDirectory_proto(self));
177 IoObject_setSlot_to_(core, SIOSYMBOL("Date"), IoDate_proto(self));
178 IoObject_setSlot_to_(core, SIOSYMBOL("Duration"), IoDuration_proto(self));
179 IoObject_setSlot_to_(core, SIOSYMBOL("WeakLink"), IoWeakLink_proto(self));
180 IoObject_setSlot_to_(core, SIOSYMBOL("Sandbox"), IoSandbox_proto(self));
181 IoObject_setSlot_to_(core, SIOSYMBOL("EditLine"), IoEditLine_proto(self));
183 #if !defined(__SYMBIAN32__)
184 IoObject_setSlot_to_(core, SIOSYMBOL("DynLib"), IoDynLib_proto(self));
185 #endif
187 //self->store =
188 //IoObject_setSlot_to_(core, SIOSYMBOL("Store"), self->store);
189 IoObject_setSlot_to_(core, SIOSYMBOL("CFunction"), cFunctionProto);
191 self->localsProto = IoState_retain_(self, IoObject_localsProto(self));
192 IoObject_setSlot_to_(core, SIOSYMBOL("Locals"), self->localsProto);
194 self->stopStatus = MESSAGE_STOP_STATUS_NORMAL;
195 self->returnValue = self->ioNil;
197 IoState_clearRetainStack(self);
199 IoState_popCollectorPause(self);
201 //Collector_collect(self->collector);
203 //io_show_mem("before IoVMCodeInit");
204 IoVMCodeInit(core);
206 //io_show_mem("after IoVMCodeInit");
207 //Collector_collect(self->collector);
208 //io_show_mem("after Collector_collect");
210 // IoState_popCollectorPause(self);
211 IoState_clearRetainStack(self);
213 Collector_collect(self->collector);
214 //io_show_mem("after IoState_clearRetainStack and Collector_collect");
218 IoState *IoState_new(void)
220 IoState *self = (IoState *)io_calloc(1, sizeof(IoState));
221 IoState_new_atAddress(self);
222 return self;
225 void IoState_setupQuickAccessSymbols(IoState *self)
227 self->activateSymbol = IoState_retain_(self, SIOSYMBOL("activate"));
228 self->forwardSymbol = IoState_retain_(self, SIOSYMBOL("forward"));
229 self->selfSymbol = IoState_retain_(self, SIOSYMBOL("self"));
230 self->setSlotSymbol = IoState_retain_(self, SIOSYMBOL("setSlot"));
231 self->setSlotWithTypeSymbol = IoState_retain_(self, SIOSYMBOL("setSlotWithType"));
232 self->updateSlotSymbol = IoState_retain_(self, SIOSYMBOL("updateSlot"));
233 self->callSymbol = IoState_retain_(self, SIOSYMBOL("call"));
234 self->typeSymbol = IoState_retain_(self, SIOSYMBOL("type"));
235 self->opShuffleSymbol = IoState_retain_(self, SIOSYMBOL("opShuffle"));
236 self->noShufflingSymbol = IoState_retain_(self, SIOSYMBOL("__noShuffling__"));
237 self->semicolonSymbol = IoState_retain_(self, SIOSYMBOL(";"));
238 self->stackSizeSymbol = IoState_retain_(self, SIOSYMBOL("stackSize"));
241 void IoState_setupSingletons(IoState *self)
243 IoObject *core = self->core;
244 // nil
246 self->ioNil = IOCLONE(self->objectProto);
247 IoObject_setSlot_to_(core, SIOSYMBOL("nil"), self->ioNil);
248 //IoObject_setSlot_to_(core, self->noShufflingSymbol, self->ioNil);
249 IoObject_setSlot_to_(core, SIOSYMBOL("Message"), IoMessage_proto(self));
250 IoObject_setSlot_to_(core, SIOSYMBOL("Call"), IoCall_proto(self));
252 self->nilMessage = IoMessage_newWithName_(self, SIOSYMBOL("nil"));
253 IoMessage_cachedResult_(self->nilMessage, self->ioNil);
254 IoState_retain_(self, self->nilMessage);
256 // true
258 self->ioTrue = IoObject_new(self);
259 IoObject_setSlot_to_(core, SIOSYMBOL("true"), self->ioTrue);
260 IoObject_setSlot_to_(self->ioTrue, SIOSYMBOL("type"), SIOSYMBOL("true"));
261 IoState_retain_(self, self->ioTrue);
263 // false
265 self->ioFalse = IoObject_new(self);
266 IoObject_setSlot_to_(core, SIOSYMBOL("false"), self->ioFalse);
267 IoObject_setSlot_to_(self->ioFalse, SIOSYMBOL("type"), SIOSYMBOL("false"));
268 IoState_retain_(self, self->ioFalse);
270 // Flow control: Normal
271 self->ioNormal = IoObject_new(self);
272 IoObject_setSlot_to_(core, SIOSYMBOL("Normal"), self->ioNormal);
273 IoObject_setSlot_to_(self->ioNormal, SIOSYMBOL("type"), SIOSYMBOL("Normal"));
274 IoState_retain_(self, self->ioNormal);
276 // Flow control: Break
277 self->ioBreak = IoObject_new(self);
278 IoObject_setSlot_to_(core, SIOSYMBOL("Break"), self->ioBreak);
279 IoObject_setSlot_to_(self->ioBreak, SIOSYMBOL("type"), SIOSYMBOL("Break"));
280 IoState_retain_(self, self->ioBreak);
282 // Flow control: Continue
283 self->ioContinue = IoObject_new(self);
284 IoObject_setSlot_to_(core, SIOSYMBOL("Continue"), self->ioContinue);
285 IoObject_setSlot_to_(self->ioContinue, SIOSYMBOL("type"), SIOSYMBOL("Continue"));
286 IoState_retain_(self, self->ioContinue);
288 // Flow control: Return
289 self->ioReturn = IoObject_new(self);
290 IoObject_setSlot_to_(core, SIOSYMBOL("Return"), self->ioReturn);
291 IoObject_setSlot_to_(self->ioReturn, SIOSYMBOL("type"), SIOSYMBOL("Return"));
292 IoState_retain_(self, self->ioReturn);
294 // Flow control: Eol
295 self->ioEol = IoObject_new(self);
296 IoObject_setSlot_to_(core, SIOSYMBOL("Eol"), self->ioEol);
297 IoObject_setSlot_to_(self->ioEol, SIOSYMBOL("type"), SIOSYMBOL("Eol"));
298 IoState_retain_(self, self->ioEol);
301 void IoState_setupCachedMessages(IoState *self)
303 self->collectedLinkMessage = IoMessage_newWithName_(self, SIOSYMBOL("collectedLink"));
304 IoState_retain_(self, self->collectedLinkMessage);
306 self->printMessage = IoMessage_newWithName_(self, SIOSYMBOL("print"));
307 IoState_retain_(self, self->printMessage);
309 self->initMessage = IoMessage_newWithName_(self, SIOSYMBOL("init"));
310 IoState_retain_(self, self->initMessage);
312 self->compareMessage = IoMessage_newWithName_(self, SIOSYMBOL("compare"));
313 IoState_retain_(self, self->compareMessage);
315 self->willFreeMessage = IoMessage_newWithName_(self, SIOSYMBOL("willFree"));
316 IoState_retain_(self, self->willFreeMessage);
318 self->runMessage = IoMessage_newWithName_(self, SIOSYMBOL("run"));
319 IoState_retain_(self, self->runMessage);
321 self->mainMessage = IoMessage_newWithName_(self, SIOSYMBOL("main"));
322 IoState_retain_(self, self->mainMessage);
324 self->opShuffleMessage = IoMessage_newWithName_(self, self->opShuffleSymbol);
325 IoState_retain_(self, self->opShuffleMessage);
327 self->yieldMessage = IoMessage_newWithName_(self, SIOSYMBOL("yield"));
328 IoState_retain_(self, self->yieldMessage);
331 IoObject *IoObject_initBindings(IoObject *self, IoObject *locals, IoMessage *m)
333 IOSTATE->bindingsInitCallback(IOSTATE, self);
334 return self;
337 void IoState_init(IoState *self)
339 if (self->bindingsInitCallback)
341 IoState_pushCollectorPause(self);
342 self->bindingsInitCallback(self, self->core);
343 IoState_popCollectorPause(self);
344 IoState_clearRetainStack(self);
348 void IoState_registerProtoWithFunc_(IoState *self, IoObject *proto, IoStateProtoFunc *func)
350 if (PHash_at_(self->primitives, (void *)func))
352 IoState_fatalError_(self, "IoState_registerProtoWithFunc_() Error: attempt to add the same proto twice");
355 IoState_retain_(self, proto);
356 PHash_at_put_(self->primitives, (void *)func, proto);
357 //printf("registered %s\n", IoObject_name(proto));
360 IoObject *IoState_protoWithName_(IoState *self, const char *name)
362 PHASH_FOREACH(self->primitives, key, proto, if (!strcmp(IoObject_name(proto), name)) { return proto; });
363 return NULL;
366 List *IoState_tagList(IoState *self) // caller must io_free returned List
368 List *tags = List_new();
369 PHASH_FOREACH(self->primitives, k, proto, List_append_(tags, IoObject_tag((IoObject *)proto)));
370 return tags;
373 void IoState_done(IoState *self)
375 // this should only be called from the main coro from outside of Io
377 List *tags = IoState_tagList(self); // need to get the tags before we io_free the protos
379 self->maxRecycledObjects = 0;
381 Collector_freeAllValues(self->collector); // io_free all objects known to the collector
382 Collector_free(self->collector);
384 List_do_(tags, (ListDoCallback *)IoTag_free);
385 List_free(tags);
387 PHash_free(self->primitives);
388 SHash_free(self->symbols);
390 LIST_DO_(self->recycledObjects, IoObject_dealloc); // this doesn't work now that objects and marks are separate
391 List_free(self->recycledObjects);
392 List_free(self->cachedNumbers);
394 MainArgs_free(self->mainArgs);
397 void IoState_free(IoState *self)
399 IoState_done(self);
400 io_free(self);
403 IoObject *IoState_lobby(IoState *self)
405 return self->lobby;
408 void IoState_setLobby_(IoState *self, IoObject *obj)
410 self->lobby = obj;
413 void MissingProtoError(void)
415 printf("missing proto\n");
418 IoObject *IoState_protoWithInitFunction_(IoState *self, IoStateProtoFunc *func)
420 IoObject *proto = PHash_at_(self->primitives, (void *)func);
422 //printf("IoState_protoWithInitFunction_(self, %p)\n", (void *)func);
424 if (!proto)
426 //MissingProtoError();
427 printf("missing proto %p\n", (void *)func);
429 IoState_fatalError_(self, "IoState_protoWithInitFunction() Error: missing proto");
432 return proto;
436 // command line ------------------------------------------------
438 void IoState_argc_argv_(IoState *self, int argc, const char *argv[])
440 IoList *args = IoList_new(self);
441 int i;
443 for (i = 1; i < argc; i ++)
445 IoList_rawAppend_(args, SIOSYMBOL(argv[i]));
449 IoObject *system = IoObject_getSlot_(self->lobby, SIOSYMBOL("System"));
450 IoObject_setSlot_to_(system, SIOSYMBOL("args"), args);
453 MainArgs_argc_argv_(self->mainArgs, argc, argv);
456 // store -------------------------------------------------------
458 IoObject *IoState_objectWithPid_(IoState *self, PID_TYPE pid)
460 return self->ioNil;
463 // doString -------------------------------------------------------
465 IoObject *IoState_rawOn_doCString_withLabel_(IoState *self,
466 IoObject *target,
467 const char *s,
468 const char *label)
470 IoMessage *m = IoMessage_newFromText_label_(self, s, label);
471 return IoMessage_locals_performOn_(m, target, target);
474 // CLI ---------------------------------------------------------
476 void IoState_rawPrompt(IoState *self)
478 int max = 1024 * 16;
479 char *s = io_calloc(1, max);
480 IoObject *result;
482 for (;;)
484 fputs("Io> ", stdout);
485 fflush(stdout);
486 fgets(s, max, stdin);
488 if (feof(stdin))
490 break;
493 result = IoState_rawOn_doCString_withLabel_(self, self->lobby, s, "IoState_rawPrompt()");
495 fputs("==> ", stdout);
496 IoObject_print(result);
497 fputs("\n", stdout);
500 io_free(s);
503 void IoState_runCLI(IoState *self)
505 IoObject *result = IoState_on_doCString_withLabel_(self, self->lobby, "CLI run", "IoState_runCLI()");
507 if (!self->shouldExit && ISNUMBER(result))
509 self->exitResult = CNUMBER(result);
513 IOVM_API int IoState_exitResult(IoState *self)
515 return self->exitResult;