Fixed a lazySlot bug where lazy slots in different objects end up pointing to the...
[io/quag.git] / libs / iovm / source / IoMessage.c
blobf7b2cf7248271663556a0ac9224b1a611e76be46
1 /*#io
2 Message ioDoc(
3 docCopyright("Steve Dekorte", 2002)
4 docLicense("BSD revised")
5 docObject("Message")
6 docDescription("""A Message object encapsulates the action of a message send. Blocks are composed of a Message and its children.
8 Terminology
10 Example;
11 A B(C D); E F
12 In the above example:
13 ...
16 Important; Modifying the message tree of a block currently in use may cause
17 a crash if a garbage collection cycle occurs. If the implementation were
18 changed to retain every called message, this could be avoided.
19 But the cost to performance seems to outweigh the need to cover this case for now.
20 """)
21 docCategory("Core")
24 #include "IoObject.h"
25 #define IOMESSAGE_C
26 #include "IoMessage.h"
27 #undef IOMESSAGE_C
28 #include "IoSeq.h"
29 #include "IoMap.h"
30 #include "IoNumber.h"
31 #include "IoState.h"
32 #include "IoCFunction.h"
33 #include "IoBlock.h"
34 #include "IoList.h"
35 #include "IoDate.h"
36 #include "IoSeq.h"
37 #include <ctype.h>
38 #include <stdarg.h>
39 #include "IoMessage_parser.h"
40 #include "IoMessage_opShuffle.h"
42 #define DATA(self) ((IoMessageData *)IoObject_dataPointer(self))
44 void IoMessage_writeToStream_(IoMessage *self, BStream *stream)
46 UArray *ba = IoMessage_description(self);
47 BStream_writeTaggedUArray_(stream, ba);
48 UArray_free(ba);
51 void IoMessage_readFromStream_(IoMessage *self, BStream *stream)
53 const char *code = BStream_readTaggedCString(stream);
54 IoMessage *m = IoMessage_newFromText_label_(IOSTATE, (char *)code, "[from store]");
55 IoMessage_copy_(self, m);
58 IoObject *IoMessage_activate(IoMessage *self, IoObject *target, IoObject *locals, IoMessage *m, IoObject *slotContext)
60 //printf("activating self %s\n", CSTRING(IoMessage_name(self)));
61 //printf("activating m %s\n", CSTRING(IoMessage_name(m)));
63 return IoMessage_locals_performOn_(self, locals, locals);
64 //return IoObject_perform(locals, locals, self);
67 IoTag *IoMessage_newTag(void *state)
69 IoTag *tag = IoTag_newWithName_("Message");
70 IoTag_state_(tag, state);
71 IoTag_cloneFunc_(tag, (IoTagCloneFunc *)IoMessage_rawClone);
72 IoTag_freeFunc_(tag, (IoTagFreeFunc *)IoMessage_free);
73 IoTag_markFunc_(tag, (IoTagMarkFunc *)IoMessage_mark);
74 IoTag_writeToStreamFunc_(tag, (IoTagWriteToStreamFunc *)IoMessage_writeToStream_);
75 IoTag_readFromStreamFunc_(tag, (IoTagReadFromStreamFunc *)IoMessage_readFromStream_);
76 IoTag_activateFunc_(tag, (IoTagActivateFunc *)IoMessage_activate);
77 return tag;
80 IoMessage *IoMessage_proto(void *state)
82 IoMethodTable methodTable[] = {
83 {"clone", IoMessage_clone},
85 {"name", IoMessage_protoName},
86 {"setName", IoMessage_protoSetName},
88 {"next", IoMessage_next},
89 {"setNext", IoMessage_setNext},
90 {"isEndOfLine", IoMessage_isEOL},
91 {"nextIgnoreEndOfLines", IoMessage_nextIgnoreEOLs},
92 {"last", IoMessage_last},
93 {"lastBeforeEndOfLine", IoMessage_lastBeforeEOL},
95 {"argAt", IoMessage_argAt},
96 {"arguments", IoMessage_arguments},
97 {"setArguments", IoMessage_setArguments},
98 {"appendArg", IoMessage_appendArg},
99 {"appendCachedArg", IoMessage_appendCachedArg},
100 {"argCount", IoMessage_argCount_},
102 {"cachedResult", IoMessage_cachedResult},
103 {"setCachedResult", IoMessage_setCachedResult},
104 {"removeCachedResult", IoMessage_removeCachedResult},
105 {"hasCachedResult", IoMessage_hasCachedResult},
107 {"lineNumber", IoMessage_lineNumber},
108 {"setLineNumber", IoMessage_setLineNumber},
110 {"characterNumber", IoMessage_characterNumber},
111 {"setCharacterNumber", IoMessage_setCharacterNumber},
113 {"label", IoMessage_label},
114 {"setLabel", IoMessage_setLabel},
116 {"code", IoMessage_descriptionString},
117 {"doInContext", IoMessage_doInContext},
118 {"fromString", IoMessage_fromString},
119 {"argsEvaluatedIn", IoMessage_argsEvaluatedIn},
120 {"asString", IoMessage_asString},
122 {"asMessageWithEvaluatedArgs", IoMessage_asMessageWithEvaluatedArgs},
124 {"opShuffle", IoMessage_opShuffle},
125 {"opShuffleC", IoMessage_opShuffle},
127 {NULL, NULL},
130 IoObject *self = IoObject_new(state);
131 IoMessageData *d;
132 IoObject_setDataPointer_(self, io_calloc(1, sizeof(IoMessageData)));
133 d = IoObject_dataPointer(self);
135 IoObject_tag_(self, IoMessage_newTag(state));
136 d->args = List_new();
137 d->name = IOSYMBOL("[unnamed]");
138 d->label = IOSYMBOL("[unlabeled]");
139 //d->charNumber = -1;
140 d->lineNumber = -1;
141 IoState_registerProtoWithFunc_((IoState *)state, self, IoMessage_proto);
143 IoObject_addMethodTable_(self, methodTable);
144 return self;
147 IoMessage *IoMessage_rawClone(IoMessage *proto)
149 IoObject *self = IoObject_rawClonePrimitive(proto);
151 IoObject_setDataPointer_(self, io_calloc(1, sizeof(IoMessageData)));
152 DATA(self)->args = List_new();
153 DATA(self)->name = DATA(proto)->name;
154 DATA(self)->label = DATA(proto)->label;
155 /* any clone really needs to be a deep copy */
156 return self;
159 IoMessage *IoMessage_new(void *state)
161 IoObject *proto = IoState_protoWithInitFunction_((IoState *)state, IoMessage_proto);
162 IoObject *self = IOCLONE(proto);
163 return self;
166 // Message shallowCopy := method(Message clone setName(name) setArguments(arguments))
168 void IoMessage_copy_(IoMessage *self, IoMessage *other)
170 DATA(self)->name = IOREF(DATA(other)->name);
173 List *l1 = DATA(self)->args;
174 List *l2 = DATA(other)->args;
175 int i, max = List_size(l2);
176 List_removeAll(l1);
178 for (i = 0; i < max; i ++)
180 List_append_(l1, IOREF(List_rawAt_(l2, i)));
185 if (DATA(other)->next) IOREF(DATA(other)->next);
186 DATA(self)->next = DATA(other)->next;
188 if (DATA(other)->cachedResult) IOREF(DATA(other)->cachedResult);
189 DATA(self)->cachedResult = DATA(other)->cachedResult;
191 //DATA(self)->charNumber = DATA(other)->charNumber;
192 DATA(self)->lineNumber = DATA(other)->lineNumber;
194 if (DATA(other)->label) IOREF(DATA(other)->label);
195 DATA(self)->label = DATA(other)->label;
198 IoMessage *IoMessage_deepCopyOf_(IoMessage *self)
200 IoMessage *child = IoMessage_new(IOSTATE);
201 int i;
203 /*printf("deep copying: %s\n", UArray_asCString(IoMessage_description(self)));*/
204 for (i = 0; i < IoMessage_argCount(self); i ++)
206 List_append_(DATA(child)->args,
207 IOREF(IoMessage_deepCopyOf_(LIST_AT_(DATA(self)->args, i))));
210 DATA(child)->name = IOREF(DATA(self)->name);
211 IoMessage_cachedResult_(child, (IoObject *)DATA(self)->cachedResult);
213 if (DATA(self)->next)
215 DATA(child)->next = IOREF(IoMessage_deepCopyOf_(DATA(self)->next));
217 /*printf("deep copy result: %s\n", UArray_asCString(IoMessage_description(child)));*/
218 return child;
221 IoMessage *IoMessage_newWithName_(void *state, IoSymbol *symbol)
223 IoMessage *self = IoMessage_new(state);
224 DATA(self)->name = IOREF(symbol);
225 return self;
228 IoMessage *IoMessage_newWithName_label_(void *state, IoSymbol *symbol, IoSymbol *label)
230 IoMessage *self = IoMessage_new(state);
231 DATA(self)->name = IOREF(symbol);
232 DATA(self)->label = IOREF(label);
233 return self;
236 IoMessage *IoMessage_newWithName_returnsValue_(void *state, IoSymbol *symbol, IoObject *v)
238 IoMessage *self = IoMessage_new(state);
239 DATA(self)->name = IOREF(symbol);
240 DATA(self)->cachedResult = IOREF(v);
241 return self;
244 IoMessage *IoMessage_newWithName_andCachedArg_(void *state, IoSymbol *symbol, IoObject *arg)
246 IoMessage *self = IoMessage_newWithName_(state, symbol);
247 IoMessage_addCachedArg_(self, arg);
248 return self;
251 void IoMessage_mark(IoMessage *self)
253 IoObject_shouldMarkIfNonNull(DATA(self)->name);
255 if (DATA(self)->args)
257 LIST_FOREACH(DATA(self)->args, i, v, IoObject_shouldMark(v));
260 IoObject_shouldMarkIfNonNull(DATA(self)->cachedResult);
261 IoObject_shouldMarkIfNonNull((IoObject *)DATA(self)->next);
262 IoObject_shouldMarkIfNonNull((IoObject *)DATA(self)->label);
265 void IoMessage_free(IoMessage *self)
267 if (DATA(self)->args)
269 List_free(DATA(self)->args);
272 io_free(IoObject_dataPointer(self));
275 List *IoMessage_args(IoMessage *self)
277 return DATA(self)->args;
280 void IoMessage_cachedResult_(IoMessage *self, IoObject *v)
282 DATA(self)->cachedResult = v ? IOREF(v) : NULL;
285 void IoMessage_label_(IoMessage *self, IoSymbol *ioSymbol) /* sets label for children too */
287 DATA(self)->label = IOREF(ioSymbol);
288 List_do_with_(DATA(self)->args, (ListDoWithCallback *)IoMessage_label_, ioSymbol);
290 if (DATA(self)->next)
292 IoMessage_label_(DATA(self)->next, ioSymbol);
296 int IoMessage_rawLineNumber(IoMessage *self)
298 return DATA(self)->lineNumber;
301 void IoMessage_rawSetLineNumber_(IoMessage *self, int n)
303 DATA(self)->lineNumber = n;
306 void IoMessage_rawSetCharNumber_(IoMessage *self, int n)
308 //DATA(self)->charNumber = n;
311 int IoMessage_rawCharNumber(IoMessage *self)
313 return 0; //DATA(self)->charNumber;
316 List *IoMessage_rawArgList(IoMessage *self)
318 return DATA(self)->args;
321 unsigned char IoMessage_isNotCached(IoMessage *self)
323 return !(DATA(self)->cachedResult);
326 unsigned char IoMessage_needsEvaluation(IoMessage *self)
328 List *args = DATA(self)->args;
329 int a = List_detect_(args, (ListDetectCallback *)IoMessage_isNotCached) != NULL;
331 if (a)
333 return 1;
336 if (DATA(self)->next && IoMessage_needsEvaluation(DATA(self)->next))
338 return 1;
341 return 0;
344 void IoMessage_addCachedArg_(IoMessage *self, IoObject *v)
346 IoMessage *m = IoMessage_new(IOSTATE);
347 IoMessage_cachedResult_(m, v);
348 IoMessage_addArg_(self, m);
351 void IoMessage_setCachedArg_to_(IoMessage *self, int n, IoObject *v)
353 IoMessage *arg;
355 while (!(arg = List_at_(DATA(self)->args, n)))
357 IoMessage_addArg_(self, IoMessage_new(IOSTATE));
360 IoMessage_cachedResult_(arg, v);
363 void IoMessage_setCachedArg_toInt_(IoMessage *self, int n, int anInt)
365 // optimized to avoid creating a number unless necessary
367 IoMessage *arg = NULL;
369 while (!(arg = List_at_(DATA(self)->args, n)))
371 List_append_(DATA(self)->args, IOREF(IoMessage_new(IOSTATE)));
374 DATA(arg)->cachedResult = IOREF(IONUMBER(anInt));
377 IoObject *IoMessage_lineNumber(IoMessage *self, IoObject *locals, IoMessage *m)
379 /*#io
380 docSlot("lineNumber",
381 "Returns the line number of the message. The charcter number
382 is typically the line number in the source text from with the message was read. ")
385 return IONUMBER(DATA(self)->lineNumber);
388 IoObject *IoMessage_setLineNumber(IoMessage *self, IoObject *locals, IoMessage *m)
390 /*#io
391 docSlot("setLineNumber(aNumber)", "Sets the line number of the message. Returns self.")
394 DATA(self)->lineNumber = IoMessage_locals_intArgAt_(m , locals, 0);
395 return self;
398 IoObject *IoMessage_characterNumber(IoMessage *self, IoObject *locals, IoMessage *m)
400 /*#io
401 docSlot("characterNumber",
402 "Returns the message character number. The charcter number is typically
403 the beggining character index in the source text from with the message was read. ")
406 return IONUMBER(0);
407 //return IONUMBER(DATA(self)->charNumber);
410 IoObject *IoMessage_setCharacterNumber(IoMessage *self, IoObject *locals, IoMessage *m)
412 /*#io
413 docSlot("setCharacterNumber(aNumber)",
414 "Sets the character number of the message. Returns self.")
417 //DATA(self)->charNumber = IoMessage_locals_intArgAt_(m , locals, 0);
418 return self;
421 IoObject *IoMessage_label(IoMessage *self, IoObject *locals, IoMessage *m)
423 /*#io
424 docSlot("label",
425 "Returns the message label. The label is typically set the the
426 name of the file from which the source code for the message was read.")
429 return DATA(self)->label;
432 IoObject *IoMessage_setLabel(IoMessage *self, IoObject *locals, IoMessage *m)
434 /*#io
435 docSlot("setLabel(aString)", "Sets the label of the message and its children. Returns self.")
438 IoMessage_label_(self, IoMessage_locals_symbolArgAt_(m , locals, 0));
439 return self;
442 // --- perform --------------------------------------------------------
444 IoObject *IoMessage_doInContext(IoMessage *self, IoObject *locals, IoMessage *m)
447 docSlot("doInContext(anObject, locals)", "Evaluates the receiver in the context of anObject. ")
450 IoObject *context = IoMessage_locals_valueArgAt_(m, (IoObject *)locals, 0);
451 if (IoMessage_argCount(m) >= 2)
453 locals = IoMessage_locals_valueArgAt_(m, (IoObject *)locals, 1);
455 else
457 // Default to using the context as the locals so that the common case of,
458 // call argAt(2) doInContext(call sender) is easier.
459 locals = context;
461 return IoMessage_locals_performOn_(self, locals, context);
464 //#define IO_DEBUG_STACK
466 IoObject *IoMessage_locals_performOn_(IoMessage *self, IoObject *locals, IoObject *target)
468 IoState *state = IOSTATE;
469 IoMessage *m = self;
470 IoObject *result = target;
471 //IoObject *semicolonSymbol = state->semicolonSymbol;
472 //IoMessageData *md;
473 IoMessageData *md;
477 //md = DATA(m);
478 //printf("%s %i\n", CSTRING(IoMessage_name(m)), state->stopStatus);
479 //printf("%s\n", CSTRING(IoMessage_name(m)));
480 md = DATA(m);
482 if(md->name == state->semicolonSymbol)
484 target = locals;
486 else
488 result = md->cachedResult; // put it on the stack?
490 if(state->debugOn)
492 char *s = CSTRING(DATA(m)->name);
493 printf("%s\n", s);
494 if (strcmp(s, "clone") == 0)
496 printf("found '%s'\n", s);
501 if (!result)
503 IoState_pushRetainPool(state);
504 #ifdef IOMESSAGE_INLINE_PERFORM
505 if(IoObject_tag(target)->performFunc == NULL)
507 result = IoObject_perform(target, locals, m);
509 else
511 result = IoObject_tag(target)->performFunc(target, locals, m);
513 #else
514 result = IoObject_tag(target)->performFunc(target, locals, m);
515 #endif
516 IoState_popRetainPoolExceptFor_(state, result);
519 //IoObject_freeIfUnreferenced(target);
520 target = result;
522 if (state->stopStatus != MESSAGE_STOP_STATUS_NORMAL)
524 return state->returnValue;
526 result = state->returnValue;
528 if (result)
530 //IoState_stackRetain_(state, result);
531 return result;
533 printf("IoBlock no result!\n");
534 return state->ioNil;
538 } while (m = md->next);
540 return result;
543 // getting arguments ---------------------------
545 int IoMessage_argCount(IoMessage *self)
547 return List_size(DATA(self)->args);
550 void IoMessage_assertArgCount_receiver_(IoMessage *self, int n, IoObject *receiver)
552 if (List_size(DATA(self)->args) < n)
554 IoState_error_(IOSTATE, self, "[%s %s] requires %i arguments\n",
555 IoObject_name(receiver), CSTRING(DATA(self)->name), n);
559 void IoMessage_locals_numberArgAt_errorForType_(IoMessage *self,
560 IoObject *locals,
561 int n,
562 const char *typeName)
564 IoObject *v = IoMessage_locals_valueArgAt_(self, locals, n);
565 IoState_error_(IOSTATE, self, "argument %i to method '%s' must be a %s, not a '%s'",
566 n, CSTRING(DATA(self)->name), typeName, IoObject_name(v));
569 IoObject *IoMessage_locals_numberArgAt_(IoMessage *self, IoObject *locals, int n)
571 IoObject *v = IoMessage_locals_valueArgAt_(self, locals, n);
573 if (!ISNUMBER(v))
575 IoMessage_locals_numberArgAt_errorForType_(self, locals, n, "Number");
578 return v;
581 int IoMessage_locals_intArgAt_(IoMessage *self, IoObject *locals, int n)
583 return IoNumber_asInt(IoMessage_locals_numberArgAt_(self, locals, n));
586 long IoMessage_locals_longArgAt_(IoMessage *self, IoObject *locals, int n)
588 return IoNumber_asLong(IoMessage_locals_numberArgAt_(self, locals, n));
591 size_t IoMessage_locals_sizetArgAt_(IoMessage *self, IoObject *locals, int n)
593 long v = IoNumber_asLong(IoMessage_locals_numberArgAt_(self, locals, n));
595 if(v < 0)
597 IoState_error_(IOSTATE, self, "IoMessage_locals_sizetArgAt_ attempt to get size_t value from negative number %i", v);
598 return 0;
601 return v;
604 double IoMessage_locals_doubleArgAt_(IoMessage *self, IoObject *locals, int n)
606 return IoNumber_asDouble(IoMessage_locals_numberArgAt_(self, locals, n));
609 float IoMessage_locals_floatArgAt_(IoMessage *self, IoObject *locals, int n)
611 return (float)IoNumber_asDouble(IoMessage_locals_numberArgAt_(self, locals, n));
614 char *IoMessage_locals_cStringArgAt_(IoMessage *self, IoObject *locals, int n)
616 return CSTRING(IoMessage_locals_symbolArgAt_(self, locals, n));
619 IoObject *IoMessage_locals_seqArgAt_(IoMessage *self, IoObject *locals, int n)
621 IoObject *v = IoMessage_locals_valueArgAt_(self, locals, n);
623 if (!ISSEQ(v))
625 IoMessage_locals_numberArgAt_errorForType_(self, locals, n, "Sequence");
628 return v;
631 IoObject *IoMessage_locals_valueAsStringArgAt_(IoMessage *self, IoObject *locals, int n)
633 return IoObject_asString_(IoMessage_locals_valueArgAt_(self, locals, n), self);
636 IoObject *IoMessage_locals_symbolArgAt_(IoMessage *self, IoObject *locals, int n)
638 IoObject *v = IoMessage_locals_valueArgAt_(self, locals, n);
640 if (!ISSEQ(v))
642 IoMessage_locals_numberArgAt_errorForType_(self, locals, n, "Sequence");
645 return IoSeq_rawAsSymbol(v);
648 IoObject *IoMessage_locals_mutableSeqArgAt_(IoMessage *self, IoObject *locals, int n)
650 IoObject *v = IoMessage_locals_valueArgAt_(self, locals, n);
652 if (!ISMUTABLESEQ(v))
654 IoMessage_locals_numberArgAt_errorForType_(self, locals, n, "mutable Sequence");
657 return v;
660 IoObject *IoMessage_locals_blockArgAt_(IoMessage *self, IoObject *locals, int n)
662 IoObject *v = IoMessage_locals_valueArgAt_(self, locals, n);
663 if (!ISBLOCK(v)) IoMessage_locals_numberArgAt_errorForType_(self, locals, n, "Block");
664 return v;
667 IoObject *IoMessage_locals_dateArgAt_(IoMessage *self, IoObject *locals, int n)
669 IoObject *v = IoMessage_locals_valueArgAt_(self, locals, n);
670 if (!ISDATE(v)) IoMessage_locals_numberArgAt_errorForType_(self, locals, n, "Date");
671 return v;
674 IoObject *IoMessage_locals_messageArgAt_(IoMessage *self, IoObject *locals, int n)
676 IoObject *v = IoMessage_locals_valueArgAt_(self, locals, n);
677 if (!ISMESSAGE(v)) IoMessage_locals_numberArgAt_errorForType_(self, locals, n, "Message");
678 return v;
681 IoObject *IoMessage_locals_listArgAt_(IoMessage *self, IoObject *locals, int n)
683 IoObject *v = IoMessage_locals_valueArgAt_(self, locals, n);
684 if (!ISLIST(v)) IoMessage_locals_numberArgAt_errorForType_(self, locals, n, "List");
685 return v;
688 IoObject *IoMessage_locals_mapArgAt_(IoMessage *self, IoObject *locals, int n)
690 IoObject *v = IoMessage_locals_valueArgAt_(self, locals, n);
691 if (!ISMAP(v)) IoMessage_locals_numberArgAt_errorForType_(self, locals, n, "Map");
692 return v;
695 // printing
697 void IoMessage_print(IoMessage *self)
699 UArray *ba = IoMessage_description(self);
701 //printf("%s\n", UArray_asCString(ba));
702 IoState_print_(IOSTATE, UArray_asCString(ba));
703 UArray_free(ba);
706 void IoMessage_printWithReturn(IoMessage *self)
708 IoMessage_print(self);
709 IoState_print_(IOSTATE, "\n");
712 UArray *IoMessage_description(IoMessage *self)
714 UArray *ba = UArray_new();
715 IoMessage_appendDescriptionTo_follow_(self, ba, 1);
716 return ba;
719 UArray *IoMessage_descriptionJustSelfAndArgs(IoMessage *self)
721 UArray *ba = UArray_new();
722 IoMessage_appendDescriptionTo_follow_(self, ba, 0);
723 return ba;
726 IoObject *IoMessage_asString(IoMessage *self, IoObject *locals, IoMessage *m)
728 /*#io
729 docSlot("asString", "Same as code().")
732 return IoMessage_descriptionString(self, locals, m);
735 void IoMessage_appendDescriptionTo_follow_(IoMessage *self, UArray *ba, int follow)
737 do {
738 IoMessageData *data = DATA(self);
740 UArray_appendCString_(ba, CSTRING(data->name));
743 int i, max = List_size(DATA(self)->args);
745 if (max > 0)
747 UArray_appendCString_(ba, "(");
749 for (i = 0; i < max; i ++)
751 IoMessage *arg = List_at_(DATA(self)->args, i);
752 IoMessage_appendDescriptionTo_follow_(arg, ba, 1);
754 if (i != max - 1)
756 UArray_appendCString_(ba, ", ");
760 UArray_appendCString_(ba, ")");
764 if (!follow)
766 return;
769 if (DATA(self)->next && DATA(self)->name != IOSTATE->semicolonSymbol) UArray_appendCString_(ba, " ");
770 if (DATA(self)->name == IOSTATE->semicolonSymbol) UArray_appendCString_(ba, "\n");
771 } while (self = DATA(self)->next);
774 // methods ---------------------------------------------------
776 IoObject *IoMessage_clone(IoMessage *self, IoObject *locals, IoMessage *m)
778 /*#io
779 docSlot("clone", "Returns a Message that is a deep copy of the receiver. ")
782 return IoMessage_deepCopyOf_(self);
785 IoObject *IoMessage_protoName(IoMessage *self, IoObject *locals, IoMessage *m)
787 /*#io
788 docSlot("name", "Returns the name of the receiver. ")
791 IoObject *s = DATA(self)->name;
792 return s;
795 IoObject *IoMessage_protoSetName(IoMessage *self, IoObject *locals, IoMessage *m)
797 /*#io
798 docSlot("setName(aString)", "Sets the name of the receiver. Returns self. ")
801 DATA(self)->name = IOREF(IoMessage_locals_symbolArgAt_(m, locals, 0));
802 //IoMessage_cacheIfPossible(self);
803 return self;
806 IoObject *IoMessage_descriptionString(IoMessage *self, IoObject *locals, IoMessage *m)
808 /*#io
809 docSlot("code",
810 "Returns a String containing a decompiled code representation of the receiver.")
813 UArray *ba = IoMessage_description(self); /* me must io_free the returned UArray */
814 return IoState_symbolWithUArray_copy_(IOSTATE, ba, 0);
818 // next -------------------------
820 IoObject *IoMessage_next(IoMessage *self, IoObject *locals, IoMessage *m)
822 /*#io
823 docSlot("next",
824 "Returns the next message in the message chain or nil if there is no next message. ")
827 return DATA(self)->next ? (IoObject *)DATA(self)->next : IONIL(self);
830 IoMessage *IoMessage_rawNext(IoMessage *self)
832 return DATA(self)->next;
835 IoObject *IoMessage_setNext(IoMessage *self, IoObject *locals, IoMessage *m)
837 /*#io
838 docSlot("setNextMessage(aMessageOrNil)",
839 "Sets the next message in the message chain to a deep copy of
840 aMessage or it removes the next message if aMessage is nil. ")
843 IoObject *v = IoMessage_locals_valueArgAt_(m , locals, 0);
844 IOASSERT(ISMESSAGE(v) || ISNIL(v), "argument must be Message or Nil");
846 if (ISNIL(v))
848 v = NULL;
851 IoMessage_rawSetNext(self, v);
852 return self;
855 void IoMessage_rawSetNext(IoMessage *self, IoMessage *m)
857 DATA(self)->next = m ? IOREF(m) : NULL;
859 #ifdef IOMESSAGE_HASPREV
861 if(m)
863 DATA(m)->previous = self;
865 #endif
868 IoObject *IoMessage_isEOL(IoMessage *self, IoObject *locals, IoMessage *m)
870 /*#io
871 docSlot("isEndOfLine", "Returns true if the message marks the end of the line. A ';' message.")
874 return IOBOOL(self, IoMessage_rawIsEOL(self));
877 int IoMessage_rawIsEOL(IoMessage *self)
879 return IoMessage_name(self) == IOSTATE->semicolonSymbol;
882 IoMessage *IoMessage_rawNextIgnoreEOLs(IoMessage *self)
884 IoMessage *next = IoMessage_rawNext(self);
886 while (next && IoMessage_rawIsEOL(next))
888 next = IoMessage_rawNext(next);
891 return next;
894 IoObject *IoMessage_nextIgnoreEOLs(IoMessage *self, IoObject *locals, IoMessage *m)
896 /*#io
897 docSlot("nextIgnoreEndOfLines",
898 "Returns the next message in the message chain which is not an EndOfLine or nil if there is no next message. ")
901 IoMessage *next = IoMessage_rawNextIgnoreEOLs(self);
902 return next ? next : IONIL(self);
905 IoMessage *IoMessage_rawLastBeforeEOL(IoMessage *self)
907 IoMessage *last = self;
908 IoMessage *next;
910 while (next = IoMessage_rawNext(last))
912 if (IoMessage_rawIsEOL(next))
914 break;
916 last = next;
919 return last;
922 IoObject *IoMessage_lastBeforeEOL(IoMessage *self, IoObject *locals, IoMessage *m)
924 /*#io
925 docSlot("lastBeforeEndOfLine",
926 "Returns the last message in the chain before the EndOfLine or nil.")
929 return IoMessage_rawLastBeforeEOL(self);
932 IoMessage *IoMessage_rawLast(IoMessage *self)
934 IoMessage *last = self;
935 IoMessage *next;
937 while (next = IoMessage_rawNext(last))
939 last = next;
942 return last;
945 IoObject *IoMessage_last(IoMessage *self, IoObject *locals, IoMessage *m)
947 /*#io
948 docSlot("last",
949 "Returns the last message in the chain.")
952 return IoMessage_rawLast(self);
955 // previous -------------------------
957 IoObject *IoMessage_previous(IoMessage *self, IoObject *locals, IoMessage *m)
959 /*#io
960 docSlot("previous",
961 "Returns the previous message in the message chain or Nil if there is no previous message. ")
963 #ifdef IOMESSAGE_HASPREV
964 return DATA(self)->previous ? (IoObject *)DATA(self)->previous : IONIL(self);
965 #else
966 return IONIL(self);
967 #endif
970 IoMessage *IoMessage_rawPrevious(IoMessage *self)
972 #ifdef IOMESSAGE_HASPREV
973 return DATA(self)->previous;
974 #else
975 return IONIL(self);
976 #endif
979 IoObject *IoMessage_setPrevious(IoMessage *self, IoObject *locals, IoMessage *m)
981 /*#io
982 docSlot("setPrevious(aMessageOrNil)",
983 "Sets the previous message in the message chain to a deep copy of
984 aMessage or it removes the previous message if aMessage is Nil. ")
987 IoObject *v = IoMessage_locals_valueArgAt_(m , locals, 0);
988 IOASSERT(ISMESSAGE(v) || ISNIL(v), "argument must be Message or Nil");
990 if (ISNIL(v))
992 v = NULL;
995 IoMessage_rawSetPrevious(self, v);
997 return self;
1000 void IoMessage_rawSetPrevious(IoMessage *self, IoMessage *m)
1002 #ifdef IOMESSAGE_HASPREV
1003 DATA(self)->previous = m ? IOREF(m) : NULL;
1005 if(m)
1007 DATA(m)->next = self;
1009 #endif
1012 // ------------------------------------------------------
1014 IoObject *IoMessage_argAt(IoMessage *self, IoObject *locals, IoMessage *m)
1016 /*#io
1017 docSlot("argAt(indexNumber)",
1018 "Returns Message object for the specified argument or Nil if none exists.")
1021 int index = IoNumber_asInt(IoMessage_locals_numberArgAt_(m , locals, 0));
1022 IoObject *v = List_at_(DATA(self)->args, index);
1023 return v ? v : IONIL(self);
1026 IoObject *IoMessage_arguments(IoMessage *self, IoObject *locals, IoMessage *m)
1028 /*#io
1029 docSlot("arguments",
1030 "Returns a list of the message objects that act as the
1031 receiver's arguments. Modifying this list will not alter the actual
1032 list of arguments. Use the arguments_() method to do that. ")
1035 IoList *argsList = IoList_new(IOSTATE);
1036 IoList_rawAddBaseList_(argsList, DATA(self)->args);
1037 return argsList;
1040 IoObject *IoMessage_setArguments(IoMessage *self, IoObject *locals, IoMessage *m)
1042 /*#io
1043 docSlot("setArguments(aListOfMessages)",
1044 "Sets the arguments of the receiver to deep copies of
1045 those contained in aListOfMessages. Returns self.")
1048 IoList *ioList = IoMessage_locals_listArgAt_(m, locals, 0);
1049 List *newArgs = IoList_rawList(ioList);
1051 List_removeAll(DATA(self)->args);
1053 LIST_FOREACH(newArgs, i, argMessage,
1055 if (!ISMESSAGE((IoMessage *)argMessage))
1057 IoState_error_(IOSTATE, m, "arguments_() takes a list containing only Message objects");
1060 List_append_(DATA(self)->args, IOREF((IoMessage *)argMessage));
1063 return self;
1066 IoObject *IoMessage_appendArg(IoMessage *self, IoObject *locals, IoMessage *m)
1068 /*#io
1069 docSlot("appendArg(aMessage)",
1070 """Adds aMessage to the argument list of receiver. Examples,
1071 <pre>
1072 Io> message(a) appendArg(message(b))
1073 ==> a(b)
1075 Io> message(a(1,2)) appendArg(message(3))
1076 ==> a(1, 2, 3)
1077 </pre>""")
1080 IoMessage *msg = IoMessage_locals_messageArgAt_(m, locals, 0);
1081 IoMessage_addArg_(self, msg);
1082 return self;
1085 IoObject *IoMessage_appendCachedArg(IoMessage *self, IoObject *locals, IoMessage *m)
1087 /*#io
1088 docSlot("appendCachedArg(aValue)",
1089 """Adds aValue to the argument list of receiver as a cachedResult.""")
1092 IoObject *v = IoMessage_locals_valueArgAt_(m, locals, 0);
1093 IoMessage_addCachedArg_(self, v);
1094 return self;
1097 IoObject *IoMessage_argCount_(IoMessage *self, IoObject *locals, IoMessage *m)
1099 /*#io
1100 docSlot("argCount",
1101 """Returns the number of arguments this message has. A faster way to do, msg arguments size. Examples,
1102 <pre>
1103 Io> message(a(1,2,3)) argCount
1104 ==> 3
1106 Io> message(a) argCount
1107 ==> 0
1108 </pre>""")
1111 return IONUMBER(IoMessage_argCount(self));
1114 IoObject *IoMessage_fromString(IoMessage *self, IoObject *locals, IoMessage *m)
1116 /*#io
1117 docSlot("fromString(aString)",
1118 "Returns a new Message object for the compiled(but not executed)
1119 result of aString. ")
1122 IoSymbol *string = IoMessage_locals_symbolArgAt_(m, locals, 0);
1123 IoSymbol *label = DATA(m)->label;
1125 if (IoMessage_argCount(m) > 1)
1127 label = IoMessage_locals_symbolArgAt_(m, locals, 1);
1130 return IoMessage_newFromText_labelSymbol_(IOSTATE, CSTRING(string), label);
1133 IoObject *IoMessage_cachedResult(IoMessage *self, IoObject *locals, IoMessage *m)
1135 /*#io
1136 docSlot("cachedResult",
1137 "Returns the cached result of the Message or Nil if there is none.")
1140 return (DATA(self)->cachedResult ? DATA(self)->cachedResult : IONIL(self));
1143 IoObject *IoMessage_setCachedResult(IoMessage *self, IoObject *locals, IoMessage *m)
1145 /*#io
1146 docSlot("setCachedResult(anObject)",
1147 "Sets the cached result of the message. Returns self.")
1150 DATA(self)->cachedResult = IOREF(IoMessage_locals_valueArgAt_(m , locals, 0));
1151 return self;
1154 IoObject *IoMessage_removeCachedResult(IoMessage *self, IoObject *locals, IoMessage *m)
1156 /*#io
1157 docSlot("removeCachedResult", "Removes the cached result of the Message.")
1160 DATA(self)->cachedResult = NULL;
1161 return self;
1164 IoObject *IoMessage_hasCachedResult(IoMessage *self, IoObject *locals, IoMessage *m)
1166 /*#io
1167 docSlot("hasCachedResult",
1168 "Returns true if there is a cached result. Nil is a valid cached result.")
1171 return IOBOOL(self, DATA(self)->cachedResult == NULL);
1174 IoObject *IoMessage_argsEvaluatedIn(IoMessage *self, IoObject *locals, IoMessage *m)
1176 /*#io
1177 docSlot("argsEvaluatedIn(anObject)",
1178 "Returns a List containing the argument messages evaluated in the
1179 context of anObject. ")
1182 IoObject *context = IoMessage_locals_valueArgAt_(m, locals, 0);
1183 IoList *args = IoList_new(IOSTATE);
1184 int i;
1186 for (i = 0; i < List_size(DATA(self)->args); i ++)
1188 IoObject *arg = IoMessage_locals_valueArgAt_(self, context, i);
1189 IoList_rawAppend_(args, arg);
1191 return args;
1194 IoObject *IoMessage_evaluatedArgs(IoMessage *self, IoObject *locals, IoMessage *m)
1197 docSlot("evaluatedArgs",
1198 "Returns a List containing the argument messages evaluated in the context.")
1201 IoList *args = IoList_new(IOSTATE);
1202 int i;
1204 for (i = 0; i < List_size(DATA(self)->args); i ++)
1206 IoObject *arg = IoMessage_locals_valueArgAt_(self, locals, i);
1207 IoList_rawAppend_(args, arg);
1210 return args;
1213 // ------------------------------
1216 IoSymbol *IoMessage_name(IoMessage *self)
1218 return DATA(self)->name;
1222 IoSymbol *IoMessage_rawLabel(IoMessage *self)
1224 return DATA(self)->label;
1227 List *IoMessage_rawArgs(IoMessage *self)
1229 return DATA(self)->args;
1232 IoMessage *IoMessage_rawArgAt_(IoMessage *self, int n)
1234 IoMessage *result = List_at_(DATA(self)->args, n);
1235 IoState_stackRetain_(IOSTATE, result);
1236 return result;
1239 void IoMessage_addArg_(IoMessage *self, IoMessage *m)
1241 List_append_(DATA(self)->args, IOREF(m));
1244 // -------------------------------
1246 UArray *IoMessage_asMinimalStackEntryDescription(IoMessage *self)
1248 IoSymbol *name = IoMessage_name(self);
1249 IoSymbol *label = IoMessage_rawLabel(self);
1250 int lineNumber = IoMessage_rawLineNumber(self);
1251 return UArray_newWithFormat_("%s:%i %s", CSTRING(label), lineNumber, CSTRING(name));
1254 void IoMessage_foreachArgs(IoMessage *self,
1255 IoObject *receiver,
1256 IoSymbol **indexSlotName,
1257 IoSymbol **valueSlotName,
1258 IoMessage **doMessage)
1260 int offset;
1262 IoMessage_assertArgCount_receiver_(self, 2, receiver);
1264 if (IoMessage_argCount(self) > 2)
1266 *indexSlotName = IoMessage_name(IoMessage_rawArgAt_(self, 0));
1267 offset = 1;
1269 else
1271 *indexSlotName = NULL; //IONIL(self);
1272 offset = 0;
1275 *valueSlotName = IoMessage_name(IoMessage_rawArgAt_(self, 0 + offset));
1276 *doMessage = IoMessage_rawArgAt_(self, 1 + offset);
1279 IoMessage *IoMessage_asMessageWithEvaluatedArgs(IoMessage *self, IoObject *locals, IoMessage *m)
1281 IoState *state = IOSTATE;
1282 IoMessage *sendMessage;
1283 int i, max = IoMessage_argCount(self);
1284 IoObject *context = locals;
1286 if (IoMessage_argCount(m) > 0)
1288 context = IoMessage_locals_valueArgAt_(m, locals, 0);
1291 if (IoMessage_needsEvaluation(self))
1293 sendMessage = IoMessage_newWithName_(state, IoMessage_name(self));
1295 else
1297 sendMessage = self;
1300 for (i = 0; i < max; i ++)
1302 IoMessage *arg = IoMessage_rawArgAt_(self, i);
1303 IoObject *result = IoMessage_locals_performOn_(arg, context, context);
1304 IoMessage_setCachedArg_to_(sendMessage, i, result);
1307 return sendMessage;