3 docCopyright("Steve Dekorte", 2002)
4 docLicense("BSD revised")
6 docDescription("""A Message object encapsulates the action of a message send. Blocks are composed of a Message and its children.
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.
26 #include "IoMessage.h"
32 #include "IoCFunction.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
);
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
);
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
},
130 IoObject
*self
= IoObject_new(state
);
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;
141 IoState_registerProtoWithFunc_((IoState
*)state
, self
, IoMessage_proto
);
143 IoObject_addMethodTable_(self
, methodTable
);
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 */
159 IoMessage
*IoMessage_new(void *state
)
161 IoObject
*proto
= IoState_protoWithInitFunction_((IoState
*)state
, IoMessage_proto
);
162 IoObject
*self
= IOCLONE(proto
);
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
);
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
);
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)));*/
221 IoMessage
*IoMessage_newWithName_(void *state
, IoSymbol
*symbol
)
223 IoMessage
*self
= IoMessage_new(state
);
224 DATA(self
)->name
= IOREF(symbol
);
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
);
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
);
244 IoMessage
*IoMessage_newWithName_andCachedArg_(void *state
, IoSymbol
*symbol
, IoObject
*arg
)
246 IoMessage
*self
= IoMessage_newWithName_(state
, symbol
);
247 IoMessage_addCachedArg_(self
, arg
);
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
;
336 if (DATA(self
)->next
&& IoMessage_needsEvaluation(DATA(self
)->next
))
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
)
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
)
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
)
391 docSlot("setLineNumber(aNumber)", "Sets the line number of the message. Returns self.")
394 DATA(self
)->lineNumber
= IoMessage_locals_intArgAt_(m
, locals
, 0);
398 IoObject
*IoMessage_characterNumber(IoMessage
*self
, IoObject
*locals
, IoMessage
*m
)
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. ")
407 //return IONUMBER(DATA(self)->charNumber);
410 IoObject
*IoMessage_setCharacterNumber(IoMessage
*self
, IoObject
*locals
, IoMessage
*m
)
413 docSlot("setCharacterNumber(aNumber)",
414 "Sets the character number of the message. Returns self.")
417 //DATA(self)->charNumber = IoMessage_locals_intArgAt_(m , locals, 0);
421 IoObject
*IoMessage_label(IoMessage
*self
, IoObject
*locals
, IoMessage
*m
)
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
)
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));
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);
457 // Default to using the context as the locals so that the common case of,
458 // call argAt(2) doInContext(call sender) is easier.
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
;
470 IoObject
*result
= target
;
471 //IoObject *semicolonSymbol = state->semicolonSymbol;
478 //printf("%s %i\n", CSTRING(IoMessage_name(m)), state->stopStatus);
479 //printf("%s\n", CSTRING(IoMessage_name(m)));
482 if(md
->name
== state
->semicolonSymbol
)
488 result
= md
->cachedResult
; // put it on the stack?
492 char *s = CSTRING(DATA(m)->name);
494 if (strcmp(s, "clone") == 0)
496 printf("found '%s'\n", s);
503 IoState_pushRetainPool(state
);
504 #ifdef IOMESSAGE_INLINE_PERFORM
505 if(IoObject_tag(target
)->performFunc
== NULL
)
507 result
= IoObject_perform(target
, locals
, m
);
511 result
= IoObject_tag(target
)->performFunc(target
, locals
, m
);
514 result
= IoObject_tag(target
)->performFunc(target
, locals
, m
);
516 IoState_popRetainPoolExceptFor_(state
, result
);
519 //IoObject_freeIfUnreferenced(target);
522 if (state
->stopStatus
!= MESSAGE_STOP_STATUS_NORMAL
)
524 return state
->returnValue
;
526 result = state->returnValue;
530 //IoState_stackRetain_(state, result);
533 printf("IoBlock no result!\n");
538 } while (m
= md
->next
);
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
,
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
);
575 IoMessage_locals_numberArgAt_errorForType_(self
, locals
, n
, "Number");
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
));
597 IoState_error_(IOSTATE
, self
, "IoMessage_locals_sizetArgAt_ attempt to get size_t value from negative number %i", 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
);
625 IoMessage_locals_numberArgAt_errorForType_(self
, locals
, n
, "Sequence");
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
);
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");
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");
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");
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");
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");
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");
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
));
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);
719 UArray
*IoMessage_descriptionJustSelfAndArgs(IoMessage
*self
)
721 UArray
*ba
= UArray_new();
722 IoMessage_appendDescriptionTo_follow_(self
, ba
, 0);
726 IoObject
*IoMessage_asString(IoMessage
*self
, IoObject
*locals
, IoMessage
*m
)
729 docSlot("asString", "Same as code().")
732 return IoMessage_descriptionString(self
, locals
, m
);
735 void IoMessage_appendDescriptionTo_follow_(IoMessage
*self
, UArray
*ba
, int follow
)
738 IoMessageData
*data
= DATA(self
);
740 UArray_appendCString_(ba
, CSTRING(data
->name
));
743 int i
, max
= List_size(DATA(self
)->args
);
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);
756 UArray_appendCString_(ba
, ", ");
760 UArray_appendCString_(ba
, ")");
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
)
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
)
788 docSlot("name", "Returns the name of the receiver. ")
791 IoObject
*s
= DATA(self
)->name
;
795 IoObject
*IoMessage_protoSetName(IoMessage
*self
, IoObject
*locals
, IoMessage
*m
)
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);
806 IoObject
*IoMessage_descriptionString(IoMessage
*self
, IoObject
*locals
, IoMessage
*m
)
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
)
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
)
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");
851 IoMessage_rawSetNext(self
, v
);
855 void IoMessage_rawSetNext(IoMessage
*self
, IoMessage
*m
)
857 DATA(self
)->next
= m
? IOREF(m
) : NULL
;
859 #ifdef IOMESSAGE_HASPREV
863 DATA(m
)->previous
= self
;
868 IoObject
*IoMessage_isEOL(IoMessage
*self
, IoObject
*locals
, IoMessage
*m
)
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
);
894 IoObject
*IoMessage_nextIgnoreEOLs(IoMessage
*self
, IoObject
*locals
, IoMessage
*m
)
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
;
910 while (next
= IoMessage_rawNext(last
))
912 if (IoMessage_rawIsEOL(next
))
922 IoObject
*IoMessage_lastBeforeEOL(IoMessage
*self
, IoObject
*locals
, IoMessage
*m
)
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
;
937 while (next
= IoMessage_rawNext(last
))
945 IoObject
*IoMessage_last(IoMessage
*self
, IoObject
*locals
, IoMessage
*m
)
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
)
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
);
970 IoMessage
*IoMessage_rawPrevious(IoMessage
*self
)
972 #ifdef IOMESSAGE_HASPREV
973 return DATA(self
)->previous
;
979 IoObject
*IoMessage_setPrevious(IoMessage
*self
, IoObject
*locals
, IoMessage
*m
)
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");
995 IoMessage_rawSetPrevious(self
, v
);
1000 void IoMessage_rawSetPrevious(IoMessage
*self
, IoMessage
*m
)
1002 #ifdef IOMESSAGE_HASPREV
1003 DATA(self
)->previous
= m
? IOREF(m
) : NULL
;
1007 DATA(m
)->next
= self
;
1012 // ------------------------------------------------------
1014 IoObject
*IoMessage_argAt(IoMessage
*self
, IoObject
*locals
, IoMessage
*m
)
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
)
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
);
1040 IoObject
*IoMessage_setArguments(IoMessage
*self
, IoObject
*locals
, IoMessage
*m
)
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
));
1066 IoObject
*IoMessage_appendArg(IoMessage
*self
, IoObject
*locals
, IoMessage
*m
)
1069 docSlot("appendArg(aMessage)",
1070 """Adds aMessage to the argument list of receiver. Examples,
1072 Io> message(a) appendArg(message(b))
1075 Io> message(a(1,2)) appendArg(message(3))
1080 IoMessage
*msg
= IoMessage_locals_messageArgAt_(m
, locals
, 0);
1081 IoMessage_addArg_(self
, msg
);
1085 IoObject
*IoMessage_appendCachedArg(IoMessage
*self
, IoObject
*locals
, IoMessage
*m
)
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
);
1097 IoObject
*IoMessage_argCount_(IoMessage
*self
, IoObject
*locals
, IoMessage
*m
)
1101 """Returns the number of arguments this message has. A faster way to do, msg arguments size. Examples,
1103 Io> message(a(1,2,3)) argCount
1106 Io> message(a) argCount
1111 return IONUMBER(IoMessage_argCount(self
));
1114 IoObject
*IoMessage_fromString(IoMessage
*self
, IoObject
*locals
, IoMessage
*m
)
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
)
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
)
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));
1154 IoObject
*IoMessage_removeCachedResult(IoMessage
*self
, IoObject
*locals
, IoMessage
*m
)
1157 docSlot("removeCachedResult", "Removes the cached result of the Message.")
1160 DATA(self
)->cachedResult
= NULL
;
1164 IoObject
*IoMessage_hasCachedResult(IoMessage
*self
, IoObject
*locals
, IoMessage
*m
)
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
)
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
);
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
);
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
);
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
);
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
);
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
,
1256 IoSymbol
**indexSlotName
,
1257 IoSymbol
**valueSlotName
,
1258 IoMessage
**doMessage
)
1262 IoMessage_assertArgCount_receiver_(self
, 2, receiver
);
1264 if (IoMessage_argCount(self
) > 2)
1266 *indexSlotName
= IoMessage_name(IoMessage_rawArgAt_(self
, 0));
1271 *indexSlotName
= NULL
; //IONIL(self);
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
));
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
);