Updating built in Io code to use += instead of x = x + y
[io/quag.git] / libs / iovm / source / IoMessage.c
blob0596ff53da44746ff55a95fd42fe0cfa8b7dc4de
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)));
184 if (DATA(other)->next) IOREF(DATA(other)->next);
185 DATA(self)->next = DATA(other)->next;
187 if (DATA(other)->cachedResult) IOREF(DATA(other)->cachedResult);
188 DATA(self)->cachedResult = DATA(other)->cachedResult;
190 IoMessage_rawCopySourceLocation(self, other);
193 void IoMessage_rawCopySourceLocation(IoMessage *self, IoMessage *other)
195 //DATA(self)->charNumber = DATA(other)->charNumber;
196 DATA(self)->lineNumber = DATA(other)->lineNumber;
198 if (DATA(other)->label) IOREF(DATA(other)->label);
199 DATA(self)->label = DATA(other)->label;
202 IoMessage *IoMessage_deepCopyOf_(IoMessage *self)
204 IoMessage *child = IoMessage_new(IOSTATE);
205 int i;
207 /*printf("deep copying: %s\n", UArray_asCString(IoMessage_description(self)));*/
208 for (i = 0; i < IoMessage_argCount(self); i ++)
210 List_append_(DATA(child)->args,
211 IOREF(IoMessage_deepCopyOf_(LIST_AT_(DATA(self)->args, i))));
214 DATA(child)->name = IOREF(DATA(self)->name);
215 IoMessage_cachedResult_(child, (IoObject *)DATA(self)->cachedResult);
217 if (DATA(self)->next)
219 DATA(child)->next = IOREF(IoMessage_deepCopyOf_(DATA(self)->next));
221 /*printf("deep copy result: %s\n", UArray_asCString(IoMessage_description(child)));*/
222 return child;
225 IoMessage *IoMessage_newWithName_(void *state, IoSymbol *symbol)
227 IoMessage *self = IoMessage_new(state);
228 DATA(self)->name = IOREF(symbol);
229 return self;
232 IoMessage *IoMessage_newWithName_label_(void *state, IoSymbol *symbol, IoSymbol *label)
234 IoMessage *self = IoMessage_new(state);
235 DATA(self)->name = IOREF(symbol);
236 DATA(self)->label = IOREF(label);
237 return self;
240 IoMessage *IoMessage_newWithName_returnsValue_(void *state, IoSymbol *symbol, IoObject *v)
242 IoMessage *self = IoMessage_new(state);
243 DATA(self)->name = IOREF(symbol);
244 DATA(self)->cachedResult = IOREF(v);
245 return self;
248 IoMessage *IoMessage_newWithName_andCachedArg_(void *state, IoSymbol *symbol, IoObject *arg)
250 IoMessage *self = IoMessage_newWithName_(state, symbol);
251 IoMessage_addCachedArg_(self, arg);
252 return self;
255 void IoMessage_mark(IoMessage *self)
257 IoObject_shouldMarkIfNonNull(DATA(self)->name);
259 if (DATA(self)->args)
261 LIST_FOREACH(DATA(self)->args, i, v, IoObject_shouldMark(v));
264 IoObject_shouldMarkIfNonNull(DATA(self)->cachedResult);
265 IoObject_shouldMarkIfNonNull((IoObject *)DATA(self)->next);
266 IoObject_shouldMarkIfNonNull((IoObject *)DATA(self)->label);
269 void IoMessage_free(IoMessage *self)
271 if (DATA(self)->args)
273 List_free(DATA(self)->args);
276 io_free(IoObject_dataPointer(self));
279 List *IoMessage_args(IoMessage *self)
281 return DATA(self)->args;
284 void IoMessage_cachedResult_(IoMessage *self, IoObject *v)
286 DATA(self)->cachedResult = v ? IOREF(v) : NULL;
289 void IoMessage_label_(IoMessage *self, IoSymbol *ioSymbol) /* sets label for children too */
291 DATA(self)->label = IOREF(ioSymbol);
292 List_do_with_(DATA(self)->args, (ListDoWithCallback *)IoMessage_label_, ioSymbol);
294 if (DATA(self)->next)
296 IoMessage_label_(DATA(self)->next, ioSymbol);
300 int IoMessage_rawLineNumber(IoMessage *self)
302 return DATA(self)->lineNumber;
305 void IoMessage_rawSetLineNumber_(IoMessage *self, int n)
307 DATA(self)->lineNumber = n;
310 void IoMessage_rawSetCharNumber_(IoMessage *self, int n)
312 //DATA(self)->charNumber = n;
315 int IoMessage_rawCharNumber(IoMessage *self)
317 return 0; //DATA(self)->charNumber;
320 List *IoMessage_rawArgList(IoMessage *self)
322 return DATA(self)->args;
325 unsigned char IoMessage_isNotCached(IoMessage *self)
327 return !(DATA(self)->cachedResult);
330 unsigned char IoMessage_needsEvaluation(IoMessage *self)
332 List *args = DATA(self)->args;
333 int a = List_detect_(args, (ListDetectCallback *)IoMessage_isNotCached) != NULL;
335 if (a)
337 return 1;
340 if (DATA(self)->next && IoMessage_needsEvaluation(DATA(self)->next))
342 return 1;
345 return 0;
348 void IoMessage_addCachedArg_(IoMessage *self, IoObject *v)
350 IoMessage *m = IoMessage_new(IOSTATE);
351 IoMessage_cachedResult_(m, v);
352 IoMessage_addArg_(self, m);
355 void IoMessage_setCachedArg_to_(IoMessage *self, int n, IoObject *v)
357 IoMessage *arg;
359 while (!(arg = List_at_(DATA(self)->args, n)))
361 IoMessage_addArg_(self, IoMessage_new(IOSTATE));
364 IoMessage_cachedResult_(arg, v);
367 void IoMessage_setCachedArg_toInt_(IoMessage *self, int n, int anInt)
369 // optimized to avoid creating a number unless necessary
371 IoMessage *arg = NULL;
373 while (!(arg = List_at_(DATA(self)->args, n)))
375 List_append_(DATA(self)->args, IOREF(IoMessage_new(IOSTATE)));
378 DATA(arg)->cachedResult = IOREF(IONUMBER(anInt));
381 IoObject *IoMessage_lineNumber(IoMessage *self, IoObject *locals, IoMessage *m)
383 /*#io
384 docSlot("lineNumber",
385 "Returns the line number of the message. The charcter number
386 is typically the line number in the source text from with the message was read. ")
389 return IONUMBER(DATA(self)->lineNumber);
392 IoObject *IoMessage_setLineNumber(IoMessage *self, IoObject *locals, IoMessage *m)
394 /*#io
395 docSlot("setLineNumber(aNumber)", "Sets the line number of the message. Returns self.")
398 DATA(self)->lineNumber = IoMessage_locals_intArgAt_(m , locals, 0);
399 return self;
402 IoObject *IoMessage_characterNumber(IoMessage *self, IoObject *locals, IoMessage *m)
404 /*#io
405 docSlot("characterNumber",
406 "Returns the message character number. The charcter number is typically
407 the beggining character index in the source text from with the message was read. ")
410 return IONUMBER(0);
411 //return IONUMBER(DATA(self)->charNumber);
414 IoObject *IoMessage_setCharacterNumber(IoMessage *self, IoObject *locals, IoMessage *m)
416 /*#io
417 docSlot("setCharacterNumber(aNumber)",
418 "Sets the character number of the message. Returns self.")
421 //DATA(self)->charNumber = IoMessage_locals_intArgAt_(m , locals, 0);
422 return self;
425 IoObject *IoMessage_label(IoMessage *self, IoObject *locals, IoMessage *m)
427 /*#io
428 docSlot("label",
429 "Returns the message label. The label is typically set the the
430 name of the file from which the source code for the message was read.")
433 return DATA(self)->label;
436 IoObject *IoMessage_setLabel(IoMessage *self, IoObject *locals, IoMessage *m)
438 /*#io
439 docSlot("setLabel(aString)", "Sets the label of the message and its children. Returns self.")
442 IoMessage_label_(self, IoMessage_locals_symbolArgAt_(m , locals, 0));
443 return self;
446 // --- perform --------------------------------------------------------
448 IoObject *IoMessage_doInContext(IoMessage *self, IoObject *locals, IoMessage *m)
451 docSlot("doInContext(anObject, locals)", "Evaluates the receiver in the context of anObject. ")
454 IoObject *context = IoMessage_locals_valueArgAt_(m, (IoObject *)locals, 0);
455 if (IoMessage_argCount(m) >= 2)
457 locals = IoMessage_locals_valueArgAt_(m, (IoObject *)locals, 1);
459 else
461 // Default to using the context as the locals so that the common case of,
462 // call argAt(2) doInContext(call sender) is easier.
463 locals = context;
465 return IoMessage_locals_performOn_(self, locals, context);
468 //#define IO_DEBUG_STACK
470 IoObject *IoMessage_locals_performOn_(IoMessage *self, IoObject *locals, IoObject *target)
472 IoState *state = IOSTATE;
473 IoMessage *m = self;
474 IoObject *result = target;
475 //IoObject *semicolonSymbol = state->semicolonSymbol;
476 //IoMessageData *md;
477 IoMessageData *md;
481 //md = DATA(m);
482 //printf("%s %i\n", CSTRING(IoMessage_name(m)), state->stopStatus);
483 //printf("%s\n", CSTRING(IoMessage_name(m)));
484 md = DATA(m);
486 if(md->name == state->semicolonSymbol)
488 target = locals;
490 else
492 result = md->cachedResult; // put it on the stack?
494 if(state->debugOn)
496 char *s = CSTRING(DATA(m)->name);
497 printf("%s\n", s);
498 if (strcmp(s, "clone") == 0)
500 printf("found '%s'\n", s);
505 if (!result)
507 IoState_pushRetainPool(state);
508 #ifdef IOMESSAGE_INLINE_PERFORM
509 if(IoObject_tag(target)->performFunc == NULL)
511 result = IoObject_perform(target, locals, m);
513 else
515 result = IoObject_tag(target)->performFunc(target, locals, m);
517 #else
518 result = IoObject_tag(target)->performFunc(target, locals, m);
519 #endif
520 IoState_popRetainPoolExceptFor_(state, result);
523 //IoObject_freeIfUnreferenced(target);
524 target = result;
526 if (state->stopStatus != MESSAGE_STOP_STATUS_NORMAL)
528 return state->returnValue;
530 result = state->returnValue;
532 if (result)
534 //IoState_stackRetain_(state, result);
535 return result;
537 printf("IoBlock no result!\n");
538 return state->ioNil;
542 } while (m = md->next);
544 return result;
547 // getting arguments ---------------------------
549 int IoMessage_argCount(IoMessage *self)
551 return List_size(DATA(self)->args);
554 void IoMessage_assertArgCount_receiver_(IoMessage *self, int n, IoObject *receiver)
556 if (List_size(DATA(self)->args) < n)
558 IoState_error_(IOSTATE, self, "[%s %s] requires %i arguments\n",
559 IoObject_name(receiver), CSTRING(DATA(self)->name), n);
563 void IoMessage_locals_numberArgAt_errorForType_(IoMessage *self,
564 IoObject *locals,
565 int n,
566 const char *typeName)
568 IoObject *v = IoMessage_locals_valueArgAt_(self, locals, n);
569 IoState_error_(IOSTATE, self, "argument %i to method '%s' must be a %s, not a '%s'",
570 n, CSTRING(DATA(self)->name), typeName, IoObject_name(v));
573 IoObject *IoMessage_locals_numberArgAt_(IoMessage *self, IoObject *locals, int n)
575 IoObject *v = IoMessage_locals_valueArgAt_(self, locals, n);
577 if (!ISNUMBER(v))
579 IoMessage_locals_numberArgAt_errorForType_(self, locals, n, "Number");
582 return v;
585 int IoMessage_locals_intArgAt_(IoMessage *self, IoObject *locals, int n)
587 return IoNumber_asInt(IoMessage_locals_numberArgAt_(self, locals, n));
590 long IoMessage_locals_longArgAt_(IoMessage *self, IoObject *locals, int n)
592 return IoNumber_asLong(IoMessage_locals_numberArgAt_(self, locals, n));
595 size_t IoMessage_locals_sizetArgAt_(IoMessage *self, IoObject *locals, int n)
597 long v = IoNumber_asLong(IoMessage_locals_numberArgAt_(self, locals, n));
599 if(v < 0)
601 IoState_error_(IOSTATE, self, "IoMessage_locals_sizetArgAt_ attempt to get size_t value from negative number %i", v);
602 return 0;
605 return v;
608 double IoMessage_locals_doubleArgAt_(IoMessage *self, IoObject *locals, int n)
610 return IoNumber_asDouble(IoMessage_locals_numberArgAt_(self, locals, n));
613 float IoMessage_locals_floatArgAt_(IoMessage *self, IoObject *locals, int n)
615 return (float)IoNumber_asDouble(IoMessage_locals_numberArgAt_(self, locals, n));
618 char *IoMessage_locals_cStringArgAt_(IoMessage *self, IoObject *locals, int n)
620 return CSTRING(IoMessage_locals_symbolArgAt_(self, locals, n));
623 IoObject *IoMessage_locals_seqArgAt_(IoMessage *self, IoObject *locals, int n)
625 IoObject *v = IoMessage_locals_valueArgAt_(self, locals, n);
627 if (!ISSEQ(v))
629 IoMessage_locals_numberArgAt_errorForType_(self, locals, n, "Sequence");
632 return v;
635 IoObject *IoMessage_locals_valueAsStringArgAt_(IoMessage *self, IoObject *locals, int n)
637 return IoObject_asString_(IoMessage_locals_valueArgAt_(self, locals, n), self);
640 IoObject *IoMessage_locals_symbolArgAt_(IoMessage *self, IoObject *locals, int n)
642 IoObject *v = IoMessage_locals_valueArgAt_(self, locals, n);
644 if (!ISSEQ(v))
646 IoMessage_locals_numberArgAt_errorForType_(self, locals, n, "Sequence");
649 return IoSeq_rawAsSymbol(v);
652 IoObject *IoMessage_locals_mutableSeqArgAt_(IoMessage *self, IoObject *locals, int n)
654 IoObject *v = IoMessage_locals_valueArgAt_(self, locals, n);
656 if (!ISMUTABLESEQ(v))
658 IoMessage_locals_numberArgAt_errorForType_(self, locals, n, "mutable Sequence");
661 return v;
664 IoObject *IoMessage_locals_blockArgAt_(IoMessage *self, IoObject *locals, int n)
666 IoObject *v = IoMessage_locals_valueArgAt_(self, locals, n);
667 if (!ISBLOCK(v)) IoMessage_locals_numberArgAt_errorForType_(self, locals, n, "Block");
668 return v;
671 IoObject *IoMessage_locals_dateArgAt_(IoMessage *self, IoObject *locals, int n)
673 IoObject *v = IoMessage_locals_valueArgAt_(self, locals, n);
674 if (!ISDATE(v)) IoMessage_locals_numberArgAt_errorForType_(self, locals, n, "Date");
675 return v;
678 IoObject *IoMessage_locals_messageArgAt_(IoMessage *self, IoObject *locals, int n)
680 IoObject *v = IoMessage_locals_valueArgAt_(self, locals, n);
681 if (!ISMESSAGE(v)) IoMessage_locals_numberArgAt_errorForType_(self, locals, n, "Message");
682 return v;
685 IoObject *IoMessage_locals_listArgAt_(IoMessage *self, IoObject *locals, int n)
687 IoObject *v = IoMessage_locals_valueArgAt_(self, locals, n);
688 if (!ISLIST(v)) IoMessage_locals_numberArgAt_errorForType_(self, locals, n, "List");
689 return v;
692 IoObject *IoMessage_locals_mapArgAt_(IoMessage *self, IoObject *locals, int n)
694 IoObject *v = IoMessage_locals_valueArgAt_(self, locals, n);
695 if (!ISMAP(v)) IoMessage_locals_numberArgAt_errorForType_(self, locals, n, "Map");
696 return v;
699 // printing
701 void IoMessage_print(IoMessage *self)
703 UArray *ba = IoMessage_description(self);
705 //printf("%s\n", UArray_asCString(ba));
706 IoState_print_(IOSTATE, UArray_asCString(ba));
707 UArray_free(ba);
710 void IoMessage_printWithReturn(IoMessage *self)
712 IoMessage_print(self);
713 IoState_print_(IOSTATE, "\n");
716 UArray *IoMessage_description(IoMessage *self)
718 UArray *ba = UArray_new();
719 IoMessage_appendDescriptionTo_follow_(self, ba, 1);
720 return ba;
723 UArray *IoMessage_descriptionJustSelfAndArgs(IoMessage *self)
725 UArray *ba = UArray_new();
726 IoMessage_appendDescriptionTo_follow_(self, ba, 0);
727 return ba;
730 IoObject *IoMessage_asString(IoMessage *self, IoObject *locals, IoMessage *m)
732 /*#io
733 docSlot("asString", "Same as code().")
736 return IoMessage_descriptionString(self, locals, m);
739 void IoMessage_appendDescriptionTo_follow_(IoMessage *self, UArray *ba, int follow)
741 do {
742 IoMessageData *data = DATA(self);
744 UArray_appendCString_(ba, CSTRING(data->name));
747 int i, max = List_size(DATA(self)->args);
749 if (max > 0)
751 UArray_appendCString_(ba, "(");
753 for (i = 0; i < max; i ++)
755 IoMessage *arg = List_at_(DATA(self)->args, i);
756 IoMessage_appendDescriptionTo_follow_(arg, ba, 1);
758 if (i != max - 1)
760 UArray_appendCString_(ba, ", ");
764 UArray_appendCString_(ba, ")");
768 if (!follow)
770 return;
773 if (DATA(self)->next && DATA(self)->name != IOSTATE->semicolonSymbol) UArray_appendCString_(ba, " ");
774 if (DATA(self)->name == IOSTATE->semicolonSymbol) UArray_appendCString_(ba, "\n");
775 } while (self = DATA(self)->next);
778 // methods ---------------------------------------------------
780 IoObject *IoMessage_clone(IoMessage *self, IoObject *locals, IoMessage *m)
782 /*#io
783 docSlot("clone", "Returns a Message that is a deep copy of the receiver. ")
786 return IoMessage_deepCopyOf_(self);
789 IoObject *IoMessage_protoName(IoMessage *self, IoObject *locals, IoMessage *m)
791 /*#io
792 docSlot("name", "Returns the name of the receiver. ")
795 IoObject *s = DATA(self)->name;
796 return s;
799 IoObject *IoMessage_protoSetName(IoMessage *self, IoObject *locals, IoMessage *m)
801 /*#io
802 docSlot("setName(aString)", "Sets the name of the receiver. Returns self. ")
805 DATA(self)->name = IOREF(IoMessage_locals_symbolArgAt_(m, locals, 0));
806 //IoMessage_cacheIfPossible(self);
807 return self;
810 IoObject *IoMessage_descriptionString(IoMessage *self, IoObject *locals, IoMessage *m)
812 /*#io
813 docSlot("code",
814 "Returns a String containing a decompiled code representation of the receiver.")
817 UArray *ba = IoMessage_description(self); /* me must io_free the returned UArray */
818 return IoState_symbolWithUArray_copy_(IOSTATE, ba, 0);
822 // next -------------------------
824 IoObject *IoMessage_next(IoMessage *self, IoObject *locals, IoMessage *m)
826 /*#io
827 docSlot("next",
828 "Returns the next message in the message chain or nil if there is no next message. ")
831 return DATA(self)->next ? (IoObject *)DATA(self)->next : IONIL(self);
834 IoMessage *IoMessage_rawNext(IoMessage *self)
836 return DATA(self)->next;
839 IoObject *IoMessage_setNext(IoMessage *self, IoObject *locals, IoMessage *m)
841 /*#io
842 docSlot("setNextMessage(aMessageOrNil)",
843 "Sets the next message in the message chain to a deep copy of
844 aMessage or it removes the next message if aMessage is nil. ")
847 IoObject *v = IoMessage_locals_valueArgAt_(m , locals, 0);
848 IOASSERT(ISMESSAGE(v) || ISNIL(v), "argument must be Message or Nil");
850 if (ISNIL(v))
852 v = NULL;
855 IoMessage_rawSetNext(self, v);
856 return self;
859 void IoMessage_rawSetNext(IoMessage *self, IoMessage *m)
861 DATA(self)->next = m ? IOREF(m) : NULL;
863 #ifdef IOMESSAGE_HASPREV
865 if(m)
867 DATA(m)->previous = self;
869 #endif
872 IoObject *IoMessage_isEOL(IoMessage *self, IoObject *locals, IoMessage *m)
874 /*#io
875 docSlot("isEndOfLine", "Returns true if the message marks the end of the line. A ';' message.")
878 return IOBOOL(self, IoMessage_rawIsEOL(self));
881 int IoMessage_rawIsEOL(IoMessage *self)
883 return IoMessage_name(self) == IOSTATE->semicolonSymbol;
886 IoMessage *IoMessage_rawNextIgnoreEOLs(IoMessage *self)
888 IoMessage *next = IoMessage_rawNext(self);
890 while (next && IoMessage_rawIsEOL(next))
892 next = IoMessage_rawNext(next);
895 return next;
898 IoObject *IoMessage_nextIgnoreEOLs(IoMessage *self, IoObject *locals, IoMessage *m)
900 /*#io
901 docSlot("nextIgnoreEndOfLines",
902 "Returns the next message in the message chain which is not an EndOfLine or nil if there is no next message. ")
905 IoMessage *next = IoMessage_rawNextIgnoreEOLs(self);
906 return next ? next : IONIL(self);
909 IoMessage *IoMessage_rawLastBeforeEOL(IoMessage *self)
911 IoMessage *last = self;
912 IoMessage *next;
914 while (next = IoMessage_rawNext(last))
916 if (IoMessage_rawIsEOL(next))
918 break;
920 last = next;
923 return last;
926 IoObject *IoMessage_lastBeforeEOL(IoMessage *self, IoObject *locals, IoMessage *m)
928 /*#io
929 docSlot("lastBeforeEndOfLine",
930 "Returns the last message in the chain before the EndOfLine or nil.")
933 return IoMessage_rawLastBeforeEOL(self);
936 IoMessage *IoMessage_rawLast(IoMessage *self)
938 IoMessage *last = self;
939 IoMessage *next;
941 while (next = IoMessage_rawNext(last))
943 last = next;
946 return last;
949 IoObject *IoMessage_last(IoMessage *self, IoObject *locals, IoMessage *m)
951 /*#io
952 docSlot("last",
953 "Returns the last message in the chain.")
956 return IoMessage_rawLast(self);
959 // previous -------------------------
961 IoObject *IoMessage_previous(IoMessage *self, IoObject *locals, IoMessage *m)
963 /*#io
964 docSlot("previous",
965 "Returns the previous message in the message chain or Nil if there is no previous message. ")
967 #ifdef IOMESSAGE_HASPREV
968 return DATA(self)->previous ? (IoObject *)DATA(self)->previous : IONIL(self);
969 #else
970 return IONIL(self);
971 #endif
974 IoMessage *IoMessage_rawPrevious(IoMessage *self)
976 #ifdef IOMESSAGE_HASPREV
977 return DATA(self)->previous;
978 #else
979 return IONIL(self);
980 #endif
983 IoObject *IoMessage_setPrevious(IoMessage *self, IoObject *locals, IoMessage *m)
985 /*#io
986 docSlot("setPrevious(aMessageOrNil)",
987 "Sets the previous message in the message chain to a deep copy of
988 aMessage or it removes the previous message if aMessage is Nil. ")
991 IoObject *v = IoMessage_locals_valueArgAt_(m , locals, 0);
992 IOASSERT(ISMESSAGE(v) || ISNIL(v), "argument must be Message or Nil");
994 if (ISNIL(v))
996 v = NULL;
999 IoMessage_rawSetPrevious(self, v);
1001 return self;
1004 void IoMessage_rawSetPrevious(IoMessage *self, IoMessage *m)
1006 #ifdef IOMESSAGE_HASPREV
1007 DATA(self)->previous = m ? IOREF(m) : NULL;
1009 if(m)
1011 DATA(m)->next = self;
1013 #endif
1016 // ------------------------------------------------------
1018 IoObject *IoMessage_argAt(IoMessage *self, IoObject *locals, IoMessage *m)
1020 /*#io
1021 docSlot("argAt(indexNumber)",
1022 "Returns Message object for the specified argument or Nil if none exists.")
1025 int index = IoNumber_asInt(IoMessage_locals_numberArgAt_(m , locals, 0));
1026 IoObject *v = List_at_(DATA(self)->args, index);
1027 return v ? v : IONIL(self);
1030 IoObject *IoMessage_arguments(IoMessage *self, IoObject *locals, IoMessage *m)
1032 /*#io
1033 docSlot("arguments",
1034 "Returns a list of the message objects that act as the
1035 receiver's arguments. Modifying this list will not alter the actual
1036 list of arguments. Use the arguments_() method to do that. ")
1039 IoList *argsList = IoList_new(IOSTATE);
1040 IoList_rawAddBaseList_(argsList, DATA(self)->args);
1041 return argsList;
1044 IoObject *IoMessage_setArguments(IoMessage *self, IoObject *locals, IoMessage *m)
1046 /*#io
1047 docSlot("setArguments(aListOfMessages)",
1048 "Sets the arguments of the receiver to deep copies of
1049 those contained in aListOfMessages. Returns self.")
1052 IoList *ioList = IoMessage_locals_listArgAt_(m, locals, 0);
1053 List *newArgs = IoList_rawList(ioList);
1055 List_removeAll(DATA(self)->args);
1057 LIST_FOREACH(newArgs, i, argMessage,
1059 if (!ISMESSAGE((IoMessage *)argMessage))
1061 IoState_error_(IOSTATE, m, "arguments_() takes a list containing only Message objects");
1064 List_append_(DATA(self)->args, IOREF((IoMessage *)argMessage));
1067 return self;
1070 IoObject *IoMessage_appendArg(IoMessage *self, IoObject *locals, IoMessage *m)
1072 /*#io
1073 docSlot("appendArg(aMessage)",
1074 """Adds aMessage to the argument list of receiver. Examples,
1075 <pre>
1076 Io> message(a) appendArg(message(b))
1077 ==> a(b)
1079 Io> message(a(1,2)) appendArg(message(3))
1080 ==> a(1, 2, 3)
1081 </pre>""")
1084 IoMessage *msg = IoMessage_locals_messageArgAt_(m, locals, 0);
1085 IoMessage_addArg_(self, msg);
1086 return self;
1089 IoObject *IoMessage_appendCachedArg(IoMessage *self, IoObject *locals, IoMessage *m)
1091 /*#io
1092 docSlot("appendCachedArg(aValue)",
1093 """Adds aValue to the argument list of receiver as a cachedResult.""")
1096 IoObject *v = IoMessage_locals_valueArgAt_(m, locals, 0);
1097 IoMessage_addCachedArg_(self, v);
1098 return self;
1101 IoObject *IoMessage_argCount_(IoMessage *self, IoObject *locals, IoMessage *m)
1103 /*#io
1104 docSlot("argCount",
1105 """Returns the number of arguments this message has. A faster way to do, msg arguments size. Examples,
1106 <pre>
1107 Io> message(a(1,2,3)) argCount
1108 ==> 3
1110 Io> message(a) argCount
1111 ==> 0
1112 </pre>""")
1115 return IONUMBER(IoMessage_argCount(self));
1118 IoObject *IoMessage_fromString(IoMessage *self, IoObject *locals, IoMessage *m)
1120 /*#io
1121 docSlot("fromString(aString)",
1122 "Returns a new Message object for the compiled(but not executed)
1123 result of aString. ")
1126 IoSymbol *string = IoMessage_locals_symbolArgAt_(m, locals, 0);
1127 IoSymbol *label = DATA(m)->label;
1129 if (IoMessage_argCount(m) > 1)
1131 label = IoMessage_locals_symbolArgAt_(m, locals, 1);
1134 return IoMessage_newFromText_labelSymbol_(IOSTATE, CSTRING(string), label);
1137 IoObject *IoMessage_cachedResult(IoMessage *self, IoObject *locals, IoMessage *m)
1139 /*#io
1140 docSlot("cachedResult",
1141 "Returns the cached result of the Message or Nil if there is none.")
1144 return (DATA(self)->cachedResult ? DATA(self)->cachedResult : IONIL(self));
1147 IoObject *IoMessage_setCachedResult(IoMessage *self, IoObject *locals, IoMessage *m)
1149 /*#io
1150 docSlot("setCachedResult(anObject)",
1151 "Sets the cached result of the message. Returns self.")
1154 DATA(self)->cachedResult = IOREF(IoMessage_locals_valueArgAt_(m , locals, 0));
1155 return self;
1158 IoObject *IoMessage_removeCachedResult(IoMessage *self, IoObject *locals, IoMessage *m)
1160 /*#io
1161 docSlot("removeCachedResult", "Removes the cached result of the Message.")
1164 DATA(self)->cachedResult = NULL;
1165 return self;
1168 IoObject *IoMessage_hasCachedResult(IoMessage *self, IoObject *locals, IoMessage *m)
1170 /*#io
1171 docSlot("hasCachedResult",
1172 "Returns true if there is a cached result. Nil is a valid cached result.")
1175 return IOBOOL(self, DATA(self)->cachedResult == NULL);
1178 IoObject *IoMessage_argsEvaluatedIn(IoMessage *self, IoObject *locals, IoMessage *m)
1180 /*#io
1181 docSlot("argsEvaluatedIn(anObject)",
1182 "Returns a List containing the argument messages evaluated in the
1183 context of anObject. ")
1186 IoObject *context = IoMessage_locals_valueArgAt_(m, locals, 0);
1187 IoList *args = IoList_new(IOSTATE);
1188 int i;
1190 for (i = 0; i < List_size(DATA(self)->args); i ++)
1192 IoObject *arg = IoMessage_locals_valueArgAt_(self, context, i);
1193 IoList_rawAppend_(args, arg);
1195 return args;
1198 IoObject *IoMessage_evaluatedArgs(IoMessage *self, IoObject *locals, IoMessage *m)
1201 docSlot("evaluatedArgs",
1202 "Returns a List containing the argument messages evaluated in the context.")
1205 IoList *args = IoList_new(IOSTATE);
1206 int i;
1208 for (i = 0; i < List_size(DATA(self)->args); i ++)
1210 IoObject *arg = IoMessage_locals_valueArgAt_(self, locals, i);
1211 IoList_rawAppend_(args, arg);
1214 return args;
1217 // ------------------------------
1220 IoSymbol *IoMessage_name(IoMessage *self)
1222 return DATA(self)->name;
1226 IoSymbol *IoMessage_rawLabel(IoMessage *self)
1228 return DATA(self)->label;
1231 List *IoMessage_rawArgs(IoMessage *self)
1233 return DATA(self)->args;
1236 IoMessage *IoMessage_rawArgAt_(IoMessage *self, int n)
1238 IoMessage *result = List_at_(DATA(self)->args, n);
1239 IoState_stackRetain_(IOSTATE, result);
1240 return result;
1243 void IoMessage_addArg_(IoMessage *self, IoMessage *m)
1245 List_append_(DATA(self)->args, IOREF(m));
1248 // -------------------------------
1250 UArray *IoMessage_asMinimalStackEntryDescription(IoMessage *self)
1252 IoSymbol *name = IoMessage_name(self);
1253 IoSymbol *label = IoMessage_rawLabel(self);
1254 int lineNumber = IoMessage_rawLineNumber(self);
1255 return UArray_newWithFormat_("%s:%i %s", CSTRING(label), lineNumber, CSTRING(name));
1258 void IoMessage_foreachArgs(IoMessage *self,
1259 IoObject *receiver,
1260 IoSymbol **indexSlotName,
1261 IoSymbol **valueSlotName,
1262 IoMessage **doMessage)
1264 int offset;
1266 IoMessage_assertArgCount_receiver_(self, 2, receiver);
1268 if (IoMessage_argCount(self) > 2)
1270 *indexSlotName = IoMessage_name(IoMessage_rawArgAt_(self, 0));
1271 offset = 1;
1273 else
1275 *indexSlotName = NULL; //IONIL(self);
1276 offset = 0;
1279 *valueSlotName = IoMessage_name(IoMessage_rawArgAt_(self, 0 + offset));
1280 *doMessage = IoMessage_rawArgAt_(self, 1 + offset);
1283 IoMessage *IoMessage_asMessageWithEvaluatedArgs(IoMessage *self, IoObject *locals, IoMessage *m)
1285 IoState *state = IOSTATE;
1286 IoMessage *sendMessage;
1287 int i, max = IoMessage_argCount(self);
1288 IoObject *context = locals;
1290 if (IoMessage_argCount(m) > 0)
1292 context = IoMessage_locals_valueArgAt_(m, locals, 0);
1295 if (IoMessage_needsEvaluation(self))
1297 sendMessage = IoMessage_newWithName_(state, IoMessage_name(self));
1299 else
1301 sendMessage = self;
1304 for (i = 0; i < max; i ++)
1306 IoMessage *arg = IoMessage_rawArgAt_(self, i);
1307 IoObject *result = IoMessage_locals_performOn_(arg, context, context);
1308 IoMessage_setCachedArg_to_(sendMessage, i, result);
1311 return sendMessage;