1 
2 //metadoc Message category Core
3 //metadoc Message copyright Steve Dekorte 2002
4 //metadoc Message license BSD revised
5 /*metadoc Message description
6 A Message object encapsulates the action of a message send.
7 Blocks are composed of a Message and its children.
8 <p>
9 Terminology
10 <pre>
11 Example:
12   Io> msg := message(A B(C D); E F)
13   ==> A B(C D); E F
14 
15 In the above example:
16   msg name            =>  A
17   msg next            =>  B(C D); E F
18   msg next arguments  =>  list(C D)
19   msg next next name  =>  ;
20   msg next next next  =>  E F
21 </pre>
22 Important: Modifying the message tree of a block currently in use may cause
23 a crash if a garbage collection cycle occurs. If the implementation were
24 changed to retain every called message, this could be avoided.
25 But the cost to performance seems to outweigh the need to cover this case for now.
26 */
27 
28 #include "IoObject.h"
29 #define IOMESSAGE_C
30 #include "IoMessage.h"
31 #undef IOMESSAGE_C
32 #include "IoSeq.h"
33 #include "IoMap.h"
34 #include "IoNumber.h"
35 #include "IoState.h"
36 #include "IoState_debug.h"
37 #include "IoCFunction.h"
38 #include "IoBlock.h"
39 #include "IoList.h"
40 #include "IoDate.h"
41 #include "IoSeq.h"
42 #include <ctype.h>
43 #include <stdarg.h>
44 #include "IoMessage_parser.h"
45 #include "IoMessage_opShuffle.h"
46 
47 static const char *protoId = "Message";
48 #define DATA(self) ((IoMessageData *)IoObject_dataPointer(self))
49 
50 /*
51 void IoMessage_writeToStream_(IoMessage *self, BStream *stream)
52 {
53 	UArray *ba = IoMessage_description(self);
54 	BStream_writeTaggedUArray_(stream, ba);
55 	UArray_free(ba);
56 }
57 
58 void IoMessage_readFromStream_(IoMessage *self, BStream *stream)
59 {
60 	const char *code = BStream_readTaggedCString(stream);
61 	IoMessage *m = IoMessage_newFromText_label_(IOSTATE, (char *)code, "[from store]");
62 	IoMessage_copy_(self, m);
63 }
64 */
65 
IoMessage_activate(IoMessage * self,IoObject * target,IoObject * locals,IoMessage * m,IoObject * slotContext)66 IoObject *IoMessage_activate(IoMessage *self, IoObject *target, IoObject *locals, IoMessage *m, IoObject *slotContext)
67 {
68 	//printf("activating self %s\n", CSTRING(IoMessage_name(self)));
69 	//printf("activating m %s\n", CSTRING(IoMessage_name(m)));
70 
71 	return IoMessage_locals_performOn_(self, locals, locals);
72 	//return IoObject_perform(locals, locals, self);
73 }
74 
IoMessage_newTag(void * state)75 IoTag *IoMessage_newTag(void *state)
76 {
77 	IoTag *tag = IoTag_newWithName_(protoId);
78 	IoTag_state_(tag, state);
79 	IoTag_cloneFunc_(tag, (IoTagCloneFunc *)IoMessage_rawClone);
80 	IoTag_freeFunc_(tag, (IoTagFreeFunc *)IoMessage_free);
81 	IoTag_markFunc_(tag, (IoTagMarkFunc *)IoMessage_mark);
82 	//IoTag_writeToStreamFunc_(tag, (IoTagWriteToStreamFunc *)IoMessage_writeToStream_);
83 	//IoTag_readFromStreamFunc_(tag, (IoTagReadFromStreamFunc *)IoMessage_readFromStream_);
84 	IoTag_activateFunc_(tag, (IoTagActivateFunc *)IoMessage_activate);
85 	return tag;
86 }
87 
IoMessage_proto(void * state)88 IoMessage *IoMessage_proto(void *state)
89 {
90 	IoMethodTable methodTable[] = {
91 	{"clone", IoMessage_clone},
92 
93 	{"name", IoMessage_protoName},
94 	{"setName", IoMessage_protoSetName},
95 
96 	{"next", IoMessage_next},
97 	{"setNext", IoMessage_setNext},
98 	{"isEndOfLine", IoMessage_isEOL},
99 	{"nextIgnoreEndOfLines", IoMessage_nextIgnoreEOLs},
100 	{"last", IoMessage_last},
101 	{"lastBeforeEndOfLine", IoMessage_lastBeforeEOL},
102 
103 	{"argAt", IoMessage_argAt},
104 	{"arguments", IoMessage_arguments},
105 	{"setArguments", IoMessage_setArguments},
106 	{"appendArg", IoMessage_appendArg},
107 	{"appendCachedArg", IoMessage_appendCachedArg},
108 	{"argCount", IoMessage_argCount_},
109 
110 	{"cachedResult", IoMessage_cachedResult},
111 	{"setCachedResult", IoMessage_setCachedResult},
112 	{"removeCachedResult", IoMessage_removeCachedResult},
113 	{"hasCachedResult", IoMessage_hasCachedResult},
114 
115 	{"lineNumber", IoMessage_lineNumber},
116 	{"setLineNumber", IoMessage_setLineNumber},
117 
118 	{"characterNumber", IoMessage_characterNumber},
119 	{"setCharacterNumber", IoMessage_setCharacterNumber},
120 
121 	{"label", IoMessage_label},
122 	{"setLabel", IoMessage_setLabel},
123 
124 	{"code", IoMessage_descriptionString},
125 	{"doInContext", IoMessage_doInContext},
126 	{"fromString", IoMessage_fromString},
127 	{"argsEvaluatedIn", IoMessage_argsEvaluatedIn},
128 	{"asString", IoMessage_asString},
129 
130 	{"asMessageWithEvaluatedArgs", IoMessage_asMessageWithEvaluatedArgs},
131 
132 	{"opShuffle", IoMessage_opShuffle},
133 	{"opShuffleC", IoMessage_opShuffle},
134 
135 	#ifdef IOMESSAGE_HASPREV
136 	{"previous", IoMessage_previous},
137 	#endif
138 
139 	{NULL, NULL},
140 	};
141 
142 	IoObject *self = IoObject_new(state);
143 	IoMessageData *d;
144 	IoObject_setDataPointer_(self, io_calloc(1, sizeof(IoMessageData)));
145 	d = IoObject_dataPointer(self);
146 
147 	IoObject_tag_(self, IoMessage_newTag(state));
148 	d->args  = List_new();
149 	d->name  = IOSYMBOL("[unnamed]");
150 	d->label = IOSYMBOL("[unlabeled]");
151 	//d->charNumber = -1;
152 	d->lineNumber = -1;
153 	IoState_registerProtoWithId_((IoState *)state, self, protoId);
154 
155 	IoObject_addMethodTable_(self, methodTable);
156 	return self;
157 }
158 
IoMessage_rawClone(IoMessage * proto)159 IoMessage *IoMessage_rawClone(IoMessage *proto)
160 {
161 	IoObject *self = IoObject_rawClonePrimitive(proto);
162 
163 	IoObject_setDataPointer_(self, io_calloc(1, sizeof(IoMessageData)));
164 	DATA(self)->args = List_new();
165 	IoMessage_rawSetName_(self, DATA(proto)->name);
166 	IoMessage_rawSetLabel_(self, DATA(proto)->label);
167 	//DATA(self)->name = DATA(proto)->name;
168 	//DATA(self)->label = DATA(proto)->label;
169 	/* any clone really needs to be a deep copy */
170 	return self;
171 }
172 
IoMessage_new(void * state)173 IoMessage *IoMessage_new(void *state)
174 {
175 	IoObject *proto = IoState_protoWithId_((IoState *)state, protoId);
176 	IoObject *self = IOCLONE(proto);
177 	return self;
178 }
179 
180 // Message shallowCopy := method(Message clone setName(name) setArguments(arguments))
181 
IoMessage_copy_(IoMessage * self,IoMessage * other)182 void IoMessage_copy_(IoMessage *self, IoMessage *other)
183 {
184 	IoMessage_rawSetName_(self, DATA(other)->name);
185 
186 	{
187 		List *l1 = DATA(self)->args;
188 		List *l2 = DATA(other)->args;
189 		size_t i, max = List_size(l2);
190 		List_removeAll(l1);
191 
192 		for (i = 0; i < max; i ++)
193 		{
194 			List_append_(l1, IOREF(List_rawAt_(l2, i)));
195 		}
196 	}
197 
198 	IoMessage_rawSetNext_(self, DATA(other)->next);
199 	IoMessage_rawSetCachedResult_(self, DATA(other)->cachedResult);
200 	IoMessage_rawCopySourceLocation(self, other);
201 }
202 
IoMessage_rawCopySourceLocation(IoMessage * self,IoMessage * other)203 void IoMessage_rawCopySourceLocation(IoMessage *self, IoMessage *other)
204 {
205 	//DATA(self)->charNumber = DATA(other)->charNumber;
206 	DATA(self)->lineNumber = DATA(other)->lineNumber;
207 	IoMessage_rawSetLabel_(self, DATA(other)->label);
208 }
209 
IoMessage_deepCopyOf_(IoMessage * self)210 IoMessage *IoMessage_deepCopyOf_(IoMessage *self)
211 {
212 	IoMessage *child = IoMessage_new(IOSTATE);
213 	int i;
214 
215 	/*printf("deep copying: %s\n", UArray_asCString(IoMessage_description(self)));*/
216 	for (i = 0; i < IoMessage_argCount(self); i ++)
217 	{
218 		List_append_(DATA(child)->args,
219 					 IOREF(IoMessage_deepCopyOf_(LIST_AT_(DATA(self)->args, i))));
220 	}
221 
222 	IoMessage_rawSetName_(child, DATA(self)->name);
223 	IoMessage_rawSetCachedResult_(child, (IoObject *)DATA(self)->cachedResult);
224 
225 	if (DATA(self)->next)
226 	{
227 		IoMessage_rawSetNext_(child, IoMessage_deepCopyOf_(DATA(self)->next));
228 	}
229 	/*printf("deep copy result: %s\n", UArray_asCString(IoMessage_description(child)));*/
230 	return child;
231 }
232 
IoMessage_newWithName_(void * state,IoSymbol * symbol)233 IoMessage *IoMessage_newWithName_(void *state, IoSymbol *symbol)
234 {
235 	IoMessage *self = IoMessage_new(state);
236 	IoMessage_rawSetName_(self, symbol);
237 	return self;
238 }
239 
IoMessage_newWithName_label_(void * state,IoSymbol * symbol,IoSymbol * label)240 IoMessage *IoMessage_newWithName_label_(void *state, IoSymbol *symbol, IoSymbol *label)
241 {
242 	IoMessage *self = IoMessage_new(state);
243 	IoMessage_rawSetName_(self, symbol);
244 	IoMessage_rawSetLabel_(self, label);
245 	return self;
246 }
247 
IoMessage_newWithName_returnsValue_(void * state,IoSymbol * symbol,IoObject * v)248 IoMessage *IoMessage_newWithName_returnsValue_(void *state, IoSymbol *symbol, IoObject *v)
249 {
250 	IoMessage *self = IoMessage_new(state);
251 	IoMessage_rawSetName_(self, symbol);
252 	IoMessage_rawSetCachedResult_(self, v);
253 	return self;
254 }
255 
IoMessage_newWithName_andCachedArg_(void * state,IoSymbol * symbol,IoObject * arg)256 IoMessage *IoMessage_newWithName_andCachedArg_(void *state, IoSymbol *symbol, IoObject *arg)
257 {
258 	IoMessage *self = IoMessage_newWithName_(state, symbol);
259 	IoMessage_addCachedArg_(self, arg);
260 	return self;
261 }
262 
IoMessage_mark(IoMessage * self)263 void IoMessage_mark(IoMessage *self)
264 {
265 	IoObject_shouldMarkIfNonNull(DATA(self)->name);
266 	IoObject_shouldMarkIfNonNull(DATA(self)->cachedResult);
267 
268 	if (DATA(self)->args)
269 	{
270 		LIST_FOREACH(DATA(self)->args, i, v, IoObject_shouldMark(v));
271 	}
272 
273 	IoObject_shouldMarkIfNonNull((IoObject *)DATA(self)->next);
274 	IoObject_shouldMarkIfNonNull((IoObject *)DATA(self)->label);
275 }
276 
IoMessage_free(IoMessage * self)277 void IoMessage_free(IoMessage *self)
278 {
279 	//IoMessageData *d = (IoMessageData *)IoObject_dataPointer(self);
280 
281 	if (DATA(self)->args)
282 	{
283 		List_free(DATA(self)->args);
284 	}
285 
286 	io_free(IoObject_dataPointer(self));
287 }
288 
IoMessage_args(IoMessage * self)289 List *IoMessage_args(IoMessage *self)
290 {
291 	return DATA(self)->args;
292 }
293 
IoMessage_rawSetCachedResult_(IoMessage * self,IoObject * v)294 void IoMessage_rawSetCachedResult_(IoMessage *self, IoObject *v)
295 {
296 	DATA(self)->cachedResult = v ? IOREF(v) : NULL;
297 }
298 
IoMessage_rawSetName_(IoMessage * self,IoObject * v)299 void IoMessage_rawSetName_(IoMessage *self, IoObject *v)
300 {
301 	DATA(self)->name = v ? IOREF(v) : NULL;
302 }
303 
IoMessage_rawSetLabel_(IoMessage * self,IoObject * v)304 void IoMessage_rawSetLabel_(IoMessage *self, IoObject *v)
305 {
306 	DATA(self)->label = v ? IOREF(v) : NULL;
307 }
308 
IoMessage_label_(IoMessage * self,IoSymbol * ioSymbol)309 void IoMessage_label_(IoMessage *self, IoSymbol *ioSymbol) /* sets label for children too */
310 {
311 	IoMessage_rawSetLabel_(self, ioSymbol);
312 	List_do_with_(DATA(self)->args, (ListDoWithCallback *)IoMessage_label_, ioSymbol);
313 
314 	if (DATA(self)->next)
315 	{
316 		IoMessage_label_(DATA(self)->next, ioSymbol);
317 	}
318 }
319 
IoMessage_rawLineNumber(IoMessage * self)320 int IoMessage_rawLineNumber(IoMessage *self)
321 {
322 	return DATA(self)->lineNumber;
323 }
324 
IoMessage_rawSetLineNumber_(IoMessage * self,int n)325 void IoMessage_rawSetLineNumber_(IoMessage *self, int n)
326 {
327 	DATA(self)->lineNumber = n;
328 }
329 
IoMessage_rawSetCharNumber_(IoMessage * self,int n)330 void IoMessage_rawSetCharNumber_(IoMessage *self, int n)
331 {
332 	//DATA(self)->charNumber = n;
333 }
334 
IoMessage_rawCharNumber(IoMessage * self)335 int IoMessage_rawCharNumber(IoMessage *self)
336 {
337 	return 0; //DATA(self)->charNumber;
338 }
339 
IoMessage_rawArgList(IoMessage * self)340 List *IoMessage_rawArgList(IoMessage *self)
341 {
342 	return DATA(self)->args;
343 }
344 
IoMessage_isNotCached(IoMessage * self)345 unsigned char IoMessage_isNotCached(IoMessage *self)
346 {
347 	return !(DATA(self)->cachedResult);
348 }
349 
IoMessage_needsEvaluation(IoMessage * self)350 unsigned char IoMessage_needsEvaluation(IoMessage *self)
351 {
352 	List *args = DATA(self)->args;
353 	int a = List_detect_(args, (ListDetectCallback *)IoMessage_isNotCached) != NULL;
354 
355 	if (a)
356 	{
357 		return 1;
358 	}
359 
360 	if (DATA(self)->next && IoMessage_needsEvaluation(DATA(self)->next))
361 	{
362 		return 1;
363 	}
364 
365 	return 0;
366 }
367 
IoMessage_addCachedArg_(IoMessage * self,IoObject * v)368 void IoMessage_addCachedArg_(IoMessage *self, IoObject *v)
369 {
370 	IoMessage *m = IoMessage_new(IOSTATE);
371 	IoMessage_rawSetCachedResult_(m, v);
372 	IoMessage_addArg_(self, m);
373 }
374 
IoMessage_setCachedArg_to_(IoMessage * self,int n,IoObject * v)375 void IoMessage_setCachedArg_to_(IoMessage *self, int n, IoObject *v)
376 {
377 	IoMessage *arg;
378 
379 	while (!(arg = List_at_(DATA(self)->args, n)))
380 	{
381 		IoMessage_addArg_(self, IoMessage_new(IOSTATE));
382 	}
383 
384 	IoMessage_rawSetCachedResult_(arg, v);
385 }
386 
IoMessage_setCachedArg_toInt_(IoMessage * self,int n,int anInt)387 void IoMessage_setCachedArg_toInt_(IoMessage *self, int n, int anInt)
388 {
389 	// optimized to avoid creating a number unless necessary
390 
391 	IoMessage *arg = NULL;
392 
393 	while (!(arg = List_at_(DATA(self)->args, n)))
394 	{
395 		List_append_(DATA(self)->args, IOREF(IoMessage_new(IOSTATE)));
396 	}
397 
398 	IoMessage_rawSetCachedResult_(arg, IONUMBER(anInt));
399 }
400 
IO_METHOD(IoMessage,lineNumber)401 IO_METHOD(IoMessage, lineNumber)
402 {
403 	/*doc Message lineNumber
404 	Returns the line number of the message. The character number
405 	is typically the line number in the source text from which the message was read.
406 	*/
407 
408 	return IONUMBER(DATA(self)->lineNumber);
409 }
410 
IO_METHOD(IoMessage,setLineNumber)411 IO_METHOD(IoMessage, setLineNumber)
412 {
413 	/*doc Message setLineNumber(aNumber)
414 	Sets the line number of the message. Returns self.
415 	*/
416 
417 	DATA(self)->lineNumber = IoMessage_locals_intArgAt_(m , locals, 0);
418 	return self;
419 }
420 
IO_METHOD(IoMessage,characterNumber)421 IO_METHOD(IoMessage, characterNumber)
422 {
423 	/*doc Message characterNumber
424 	Returns the message character number. The character number is typically
425 	the beginning character index in the source text from which the message was read.
426 	*/
427 
428 	return IONUMBER(0);
429 	//return IONUMBER(DATA(self)->charNumber);
430 }
431 
IO_METHOD(IoMessage,setCharacterNumber)432 IO_METHOD(IoMessage, setCharacterNumber)
433 {
434 	/*doc Message setCharacterNumber(aNumber)
435 	Sets the character number of the message. Returns self.
436 	*/
437 
438 	//DATA(self)->charNumber = IoMessage_locals_intArgAt_(m , locals, 0);
439 	return self;
440 }
441 
IO_METHOD(IoMessage,label)442 IO_METHOD(IoMessage, label)
443 {
444 	/*doc Message label
445 	Returns the message label. The label is typically set to the
446 	name of the file from which the source code for the message was read.
447 	*/
448 
449 	return DATA(self)->label;
450 }
451 
IO_METHOD(IoMessage,setLabel)452 IO_METHOD(IoMessage, setLabel)
453 {
454 	/*doc Message setLabel(aString)
455 	Sets the label of the message and its children. Returns self.
456 	*/
457 
458 	IoMessage_label_(self, IoMessage_locals_symbolArgAt_(m , locals, 0));
459 	return self;
460 }
461 
462 // --- perform --------------------------------------------------------
463 
IO_METHOD(IoMessage,doInContext)464 IO_METHOD(IoMessage, doInContext)
465 {
466 	/*doc Message doInContext(anObject, locals)
467 	Evaluates the receiver in the context of anObject. Optional <tt>locals</tt>
468 	object is used as message sender. <tt>anObject</tt> is used as sender otherwise.
469 	*/
470 
471 	IoObject *context = IoMessage_locals_valueArgAt_(m, (IoObject *)locals, 0);
472 	if (IoMessage_argCount(m) >= 2)
473 	{
474 		locals = IoMessage_locals_valueArgAt_(m, (IoObject *)locals, 1);
475 	}
476 	else
477 	{
478 		// Default to using the context as the locals so that the common case of,
479 		// call argAt(2) doInContext(call sender) is easier.
480 		locals = context;
481 	}
482 	return IoMessage_locals_performOn_(self, locals, context);
483 }
484 
485 //#define IO_DEBUG_STACK
486 
IoMessage_locals_performOn_(IoMessage * self,IoObject * locals,IoObject * target)487 IoObject *IoMessage_locals_performOn_(IoMessage *self, IoObject *locals, IoObject *target)
488 {
489 	IoState *state = IOSTATE;
490 	IoMessage *m = self;
491 	IoObject *result = target;
492 	IoObject *cachedTarget = target;
493 	//IoObject *semicolonSymbol = state->semicolonSymbol;
494 	//IoMessageData *md;
495 	IoMessageData *md;
496 
497 	if (state->receivedSignal)
498 	{
499 		IoState_callUserInterruptHandler(IOSTATE);
500 	}
501 
502 	do
503 	{
504 		//md = DATA(m);
505 
506 		//printf("%s %i\n", CSTRING(IoMessage_name(m)), state->stopStatus);
507 		//printf(" %s\n", CSTRING(IoMessage_name(m)));
508 		if(state->showAllMessages)
509 		{
510 			printf("M:%s:%s:%i\n", CSTRING(IoMessage_name(m)), CSTRING(IoMessage_rawLabel(m)), IoMessage_rawLineNumber(m));
511 		}
512 
513 		md = DATA(m);
514 
515 		if(md->name == state->semicolonSymbol)
516 		{
517 			target = cachedTarget;
518 		}
519 		else
520 		{
521 			result = md->cachedResult; // put it on the stack?
522 			/*
523 			if(state->debugOn)
524 			{
525 				char *s = CSTRING(DATA(m)->name);
526 				printf("%s\n", s);
527 				if (strcmp(s, "clone") == 0)
528 				{
529 					printf("found '%s'\n", s);
530 				}
531 			}
532 			*/
533 
534 			if (!result)
535 			{
536 				IoState_pushRetainPool(state);
537 #ifdef IOMESSAGE_INLINE_PERFORM
538 				if(IoObject_tag(target)->performFunc == NULL)
539 				{
540 					result = IoObject_perform(target, locals, m);
541 				}
542 				else
543 				{
544 					result = IoObject_tag(target)->performFunc(target, locals, m);
545 				}
546 #else
547 				result = IoObject_tag(target)->performFunc(target, locals, m);
548 #endif
549 				IoState_popRetainPoolExceptFor_(state, result);
550 			}
551 
552 			//IoObject_freeIfUnreferenced(target);
553 			target = result;
554 
555 			if (state->stopStatus != MESSAGE_STOP_STATUS_NORMAL)
556 			{
557 					return state->returnValue;
558 					/*
559 					result = state->returnValue;
560 
561 					if (result)
562 					{
563 						//IoState_stackRetain_(state, result);
564 						return result;
565 					}
566 					printf("IoBlock no result!\n");
567 					return state->ioNil;
568 					*/
569 			}
570 		}
571 	} while ((m = md->next));
572 
573 	return result;
574 }
575 
576 // getting arguments ---------------------------
577 
IoMessage_argCount(IoMessage * self)578 int IoMessage_argCount(IoMessage *self)
579 {
580 	return (int)List_size(DATA(self)->args);
581 }
582 
IoMessage_assertArgCount_receiver_(IoMessage * self,int n,IoObject * receiver)583 void IoMessage_assertArgCount_receiver_(IoMessage *self, int n, IoObject *receiver)
584 {
585 	if (List_size(DATA(self)->args) < n)
586 	{
587 		IoState_error_(IOSTATE, self, "[%s %s] requires %i arguments\n",
588 					   IoObject_name(receiver), CSTRING(DATA(self)->name), n);
589 	}
590 }
591 
IoMessage_locals_numberArgAt_errorForType_(IoMessage * self,IoObject * locals,int n,const char * typeName)592 void IoMessage_locals_numberArgAt_errorForType_(IoMessage *self,
593 												IoObject *locals,
594 												int n,
595 												const char *typeName)
596 {
597 	IoObject *v = IoMessage_locals_valueArgAt_(self, locals, n);
598 	IoState_error_(IOSTATE, self, "argument %i to method '%s' must be a %s, not a '%s'",
599 				   n, CSTRING(DATA(self)->name), typeName, IoObject_name(v));
600 }
601 
IoMessage_locals_numberArgAt_(IoMessage * self,IoObject * locals,int n)602 IoObject *IoMessage_locals_numberArgAt_(IoMessage *self, IoObject *locals, int n)
603 {
604 	IoObject *v = IoMessage_locals_valueArgAt_(self, locals, n);
605 
606 	if (!ISNUMBER(v))
607 	{
608 		IoMessage_locals_numberArgAt_errorForType_(self, locals, n, "Number");
609 	}
610 
611 	return v;
612 }
613 
IoMessage_locals_boolArgAt_(IoMessage * self,IoObject * locals,int n)614 int IoMessage_locals_boolArgAt_(IoMessage *self, IoObject *locals, int n)
615 {
616 	IoObject *v = IoMessage_locals_valueArgAt_(self, locals, n);
617 
618 	return !ISNIL(v) && !ISFALSE(v);
619 }
620 
IoMessage_locals_intArgAt_(IoMessage * self,IoObject * locals,int n)621 int IoMessage_locals_intArgAt_(IoMessage *self, IoObject *locals, int n)
622 {
623 	return IoNumber_asInt(IoMessage_locals_numberArgAt_(self, locals, n));
624 }
625 
IoMessage_locals_longArgAt_(IoMessage * self,IoObject * locals,int n)626 long IoMessage_locals_longArgAt_(IoMessage *self, IoObject *locals, int n)
627 {
628 	return IoNumber_asLong(IoMessage_locals_numberArgAt_(self, locals, n));
629 }
630 
IoMessage_locals_sizetArgAt_(IoMessage * self,IoObject * locals,int n)631 size_t IoMessage_locals_sizetArgAt_(IoMessage *self, IoObject *locals, int n)
632 {
633 	long v = IoNumber_asLong(IoMessage_locals_numberArgAt_(self, locals, n));
634 
635 	if(v < 0)
636 	{
637 		IoState_error_(IOSTATE, self, "IoMessage_locals_sizetArgAt_ attempt to get size_t value from negative number %i", v);
638 		return 0;
639 	}
640 
641 	return v;
642 }
643 
IoMessage_locals_doubleArgAt_(IoMessage * self,IoObject * locals,int n)644 double IoMessage_locals_doubleArgAt_(IoMessage *self, IoObject *locals, int n)
645 {
646 	return IoNumber_asDouble(IoMessage_locals_numberArgAt_(self, locals, n));
647 }
648 
IoMessage_locals_floatArgAt_(IoMessage * self,IoObject * locals,int n)649 float IoMessage_locals_floatArgAt_(IoMessage *self, IoObject *locals, int n)
650 {
651 	return (float)IoNumber_asDouble(IoMessage_locals_numberArgAt_(self, locals, n));
652 }
653 
IoMessage_locals_cStringArgAt_(IoMessage * self,IoObject * locals,int n)654 char *IoMessage_locals_cStringArgAt_(IoMessage *self, IoObject *locals, int n)
655 {
656 	return CSTRING(IoMessage_locals_symbolArgAt_(self, locals, n));
657 }
658 
IoMessage_locals_seqArgAt_(IoMessage * self,IoObject * locals,int n)659 IoObject *IoMessage_locals_seqArgAt_(IoMessage *self, IoObject *locals, int n)
660 {
661 	IoObject *v = IoMessage_locals_valueArgAt_(self, locals, n);
662 
663 	if (!ISSEQ(v))
664 	{
665 		IoMessage_locals_numberArgAt_errorForType_(self, locals, n, "Sequence");
666 	}
667 
668 	return v;
669 }
670 
IoMessage_locals_valueAsStringArgAt_(IoMessage * self,IoObject * locals,int n)671 IoObject *IoMessage_locals_valueAsStringArgAt_(IoMessage *self, IoObject *locals, int n)
672 {
673 	return IoObject_asString_(IoMessage_locals_valueArgAt_(self, locals, n), self);
674 }
675 
IoMessage_locals_symbolArgAt_(IoMessage * self,IoObject * locals,int n)676 IoObject *IoMessage_locals_symbolArgAt_(IoMessage *self, IoObject *locals, int n)
677 {
678 	IoObject *v = IoMessage_locals_valueArgAt_(self, locals, n);
679 
680 	if (!ISSEQ(v))
681 	{
682 		IoMessage_locals_numberArgAt_errorForType_(self, locals, n, "Sequence");
683 	}
684 
685 	return IoSeq_rawAsSymbol(v);
686 }
687 
IoMessage_locals_mutableSeqArgAt_(IoMessage * self,IoObject * locals,int n)688 IoObject *IoMessage_locals_mutableSeqArgAt_(IoMessage *self, IoObject *locals, int n)
689 {
690 	IoObject *v = IoMessage_locals_valueArgAt_(self, locals, n);
691 
692 	if (!ISMUTABLESEQ(v))
693 	{
694 		IoMessage_locals_numberArgAt_errorForType_(self, locals, n, "mutable Sequence");
695 	}
696 
697 	return v;
698 }
699 
IoMessage_locals_blockArgAt_(IoMessage * self,IoObject * locals,int n)700 IoObject *IoMessage_locals_blockArgAt_(IoMessage *self, IoObject *locals, int n)
701 {
702 	IoObject *v = IoMessage_locals_valueArgAt_(self, locals, n);
703 	if (!ISBLOCK(v)) IoMessage_locals_numberArgAt_errorForType_(self, locals, n, "Block");
704 	return v;
705 }
706 
IoMessage_locals_dateArgAt_(IoMessage * self,IoObject * locals,int n)707 IoObject *IoMessage_locals_dateArgAt_(IoMessage *self, IoObject *locals, int n)
708 {
709 	IoObject *v = IoMessage_locals_valueArgAt_(self, locals, n);
710 	if (!ISDATE(v)) IoMessage_locals_numberArgAt_errorForType_(self, locals, n, "Date");
711 	return v;
712 }
713 
IoMessage_locals_messageArgAt_(IoMessage * self,IoObject * locals,int n)714 IoObject *IoMessage_locals_messageArgAt_(IoMessage *self, IoObject *locals, int n)
715 {
716 	IoObject *v = IoMessage_locals_valueArgAt_(self, locals, n);
717 	if (!ISMESSAGE(v)) IoMessage_locals_numberArgAt_errorForType_(self, locals, n, "Message");
718 	return v;
719 }
720 
IoMessage_locals_listArgAt_(IoMessage * self,IoObject * locals,int n)721 IoObject *IoMessage_locals_listArgAt_(IoMessage *self, IoObject *locals, int n)
722 {
723 	IoObject *v = IoMessage_locals_valueArgAt_(self, locals, n);
724 	if (!ISLIST(v)) IoMessage_locals_numberArgAt_errorForType_(self, locals, n, "List");
725 	return v;
726 }
727 
IoMessage_locals_mapArgAt_(IoMessage * self,IoObject * locals,int n)728 IoObject *IoMessage_locals_mapArgAt_(IoMessage *self, IoObject *locals, int n)
729 {
730 	IoObject *v = IoMessage_locals_valueArgAt_(self, locals, n);
731 	if (!ISMAP(v)) IoMessage_locals_numberArgAt_errorForType_(self, locals, n, "Map");
732 	return v;
733 }
734 
735 // printing
736 
IoMessage_print(IoMessage * self)737 void IoMessage_print(IoMessage *self)
738 {
739 	UArray *ba = IoMessage_description(self);
740 
741 	//printf("%s\n", UArray_asCString(ba));
742 	IoState_print_(IOSTATE, UArray_asCString(ba));
743 	UArray_free(ba);
744 }
745 
IoMessage_printWithReturn(IoMessage * self)746 void IoMessage_printWithReturn(IoMessage *self)
747 {
748 	IoMessage_print(self);
749 	IoState_print_(IOSTATE, "\n");
750 }
751 
IoMessage_description(IoMessage * self)752 UArray *IoMessage_description(IoMessage *self)
753 {
754 	UArray *ba = UArray_new();
755 	IoMessage_appendDescriptionTo_follow_(self, ba, 1);
756 	return ba;
757 }
758 
IoMessage_descriptionJustSelfAndArgs(IoMessage * self)759 UArray *IoMessage_descriptionJustSelfAndArgs(IoMessage *self)
760 {
761 	UArray *ba = UArray_new();
762 	IoMessage_appendDescriptionTo_follow_(self, ba, 0);
763 	return ba;
764 }
765 
IO_METHOD(IoMessage,asString)766 IO_METHOD(IoMessage, asString)
767 {
768 	/*doc Message asString
769 	Same as code().
770 	*/
771 
772 	return IoMessage_descriptionString(self, locals, m);
773 }
774 
IoMessage_appendDescriptionTo_follow_(IoMessage * self,UArray * ba,int follow)775 void IoMessage_appendDescriptionTo_follow_(IoMessage *self, UArray *ba, int follow)
776 {
777 	do {
778 		IoMessageData *data = DATA(self);
779 
780 		UArray_appendCString_(ba, CSTRING(data->name));
781 
782 		{
783 			size_t i, max = List_size(DATA(self)->args);
784 
785 			if (max > 0)
786 			{
787 				UArray_appendCString_(ba, "(");
788 
789 				for (i = 0; i < max; i ++)
790 				{
791 					IoMessage *arg = List_at_(DATA(self)->args, i);
792 					IoMessage_appendDescriptionTo_follow_(arg, ba, 1);
793 
794 					if (i != max - 1)
795 					{
796 						UArray_appendCString_(ba, ", ");
797 					}
798 				}
799 
800 				UArray_appendCString_(ba, ")");
801 			}
802 		}
803 
804 		if (!follow)
805 		{
806 			return;
807 		}
808 
809 		if (DATA(self)->next && DATA(self)->name != IOSTATE->semicolonSymbol) UArray_appendCString_(ba, " ");
810 		if (DATA(self)->name == IOSTATE->semicolonSymbol) UArray_appendCString_(ba, "\n");
811 	} while ((self = DATA(self)->next));
812 }
813 
814 //  methods ---------------------------------------------------
815 
IO_METHOD(IoMessage,clone)816 IO_METHOD(IoMessage, clone)
817 {
818 	/*doc Message clone
819 	Returns a Message that is a deep copy of the receiver.
820 	*/
821 
822 	return IoMessage_deepCopyOf_(self);
823 }
824 
IO_METHOD(IoMessage,protoName)825 IO_METHOD(IoMessage, protoName)
826 {
827 	/*doc Message name
828 	Returns the name of the receiver.
829 	*/
830 
831 	IoObject *s = DATA(self)->name;
832 	return s;
833 }
834 
IO_METHOD(IoMessage,protoSetName)835 IO_METHOD(IoMessage, protoSetName)
836 {
837 	/*doc Message setName(aString)
838 	Sets the name of the receiver. Returns self.
839 	*/
840 	IoMessage_rawSetName_(self, IoMessage_locals_symbolArgAt_(m, locals, 0));
841 	//IoMessage_cacheIfPossible(self);
842 	return self;
843 }
844 
IO_METHOD(IoMessage,descriptionString)845 IO_METHOD(IoMessage, descriptionString)
846 {
847 	/*doc Message code
848 	Returns a String containing a decompiled code representation of the receiver.
849 	*/
850 
851 	UArray *ba = IoMessage_description(self); /* me must io_free the returned UArray */
852 	return IoState_symbolWithUArray_copy_(IOSTATE, ba, 0);
853 }
854 
855 
856 // next -------------------------
857 
IO_METHOD(IoMessage,next)858 IO_METHOD(IoMessage, next)
859 {
860 	/*doc Message next
861 	Returns the next message in the message chain or nil if there is no next message.
862 	*/
863 
864 	return DATA(self)->next ? (IoObject *)DATA(self)->next : IONIL(self);
865 }
866 
IoMessage_rawNext(IoMessage * self)867 IoMessage *IoMessage_rawNext(IoMessage *self)
868 {
869 	return DATA(self)->next;
870 }
871 
IO_METHOD(IoMessage,setNext)872 IO_METHOD(IoMessage, setNext)
873 {
874 	/*doc Message setNext(aMessageOrNil)
875 	Sets the next message in the message chain to a deep copy of
876 	aMessage or it removes the next message if aMessage is nil.
877 	*/
878 
879 	IoObject *v = IoMessage_locals_valueArgAt_(m , locals, 0);
880 	IOASSERT(ISMESSAGE(v) || ISNIL(v), "argument must be Message or Nil");
881 
882 	if (ISNIL(v))
883 	{
884 		v = NULL;
885 	}
886 
887 	IoMessage_rawSetNext_(self, v);
888 	return self;
889 }
890 
IoMessage_rawSetNext_(IoMessage * self,IoMessage * m)891 void IoMessage_rawSetNext_(IoMessage *self, IoMessage *m)
892 {
893 	DATA(self)->next = m ? IOREF(m) : NULL;
894 
895 #ifdef IOMESSAGE_HASPREV
896 	if(m)
897 	{
898 		DATA(m)->previous = self;
899 	}
900 #endif
901 }
902 
IO_METHOD(IoMessage,isEOL)903 IO_METHOD(IoMessage, isEOL)
904 {
905 	/*doc Message isEndOfLine
906 	Returns true if the message marks the end of the line. A ';' message.
907 	*/
908 
909 	return IOBOOL(self, IoMessage_rawIsEOL(self));
910 }
911 
IoMessage_rawIsEOL(IoMessage * self)912 int IoMessage_rawIsEOL(IoMessage *self)
913 {
914 	return IoMessage_name(self) == IOSTATE->semicolonSymbol;
915 }
916 
IoMessage_rawNextIgnoreEOLs(IoMessage * self)917 IoMessage *IoMessage_rawNextIgnoreEOLs(IoMessage *self)
918 {
919 	IoMessage *next = IoMessage_rawNext(self);
920 
921 	while (next && IoMessage_rawIsEOL(next))
922 	{
923 		next = IoMessage_rawNext(next);
924 	}
925 
926 	return next;
927 }
928 
IO_METHOD(IoMessage,nextIgnoreEOLs)929 IO_METHOD(IoMessage, nextIgnoreEOLs)
930 {
931 	/*doc Message nextIgnoreEndOfLines
932 	Returns the next message in the message chain which is not an
933 	EndOfLine or nil if there is no next message.
934 	*/
935 
936 	IoMessage *next = IoMessage_rawNextIgnoreEOLs(self);
937 	return next ? next : IONIL(self);
938 }
939 
IoMessage_rawLastBeforeEOL(IoMessage * self)940 IoMessage *IoMessage_rawLastBeforeEOL(IoMessage *self)
941 {
942 	IoMessage *last = self;
943 	IoMessage *next;
944 
945 	while ((next = IoMessage_rawNext(last)))
946 	{
947 		if (IoMessage_rawIsEOL(next))
948 		{
949 			break;
950 		}
951 		last = next;
952 	}
953 
954 	return last;
955 }
956 
IO_METHOD(IoMessage,lastBeforeEOL)957 IO_METHOD(IoMessage, lastBeforeEOL)
958 {
959 	/*doc Message lastBeforeEndOfLine
960 	Returns the last message in the chain before the EndOfLine or nil.
961 	*/
962 
963 	return IoMessage_rawLastBeforeEOL(self);
964 }
965 
IoMessage_rawLast(IoMessage * self)966 IoMessage *IoMessage_rawLast(IoMessage *self)
967 {
968 	IoMessage *last = self;
969 	IoMessage *next;
970 
971 	while ((next = IoMessage_rawNext(last)))
972 	{
973 		last = next;
974 	}
975 
976 	return last;
977 }
978 
IO_METHOD(IoMessage,last)979 IO_METHOD(IoMessage, last)
980 {
981 	/*doc Message last
982 	Returns the last message in the chain.
983 	*/
984 
985 	return IoMessage_rawLast(self);
986 }
987 
988 // previous -------------------------
989 
IO_METHOD(IoMessage,previous)990 IO_METHOD(IoMessage, previous)
991 {
992 	/*doc Message previous
993 	Returns the previous message in the message chain or Nil if there is no previous message.
994 	*/
995 
996 #ifdef IOMESSAGE_HASPREV
997 	return DATA(self)->previous ? (IoObject *)DATA(self)->previous : IONIL(self);
998 #else
999 	return IONIL(self);
1000 #endif
1001 }
1002 
IoMessage_rawPrevious(IoMessage * self)1003 IoMessage *IoMessage_rawPrevious(IoMessage *self)
1004 {
1005 #ifdef IOMESSAGE_HASPREV
1006 	return DATA(self)->previous;
1007 #else
1008 	return IONIL(self);
1009 #endif
1010 }
1011 
IO_METHOD(IoMessage,setPrevious)1012 IO_METHOD(IoMessage, setPrevious)
1013 {
1014 	/*doc Message setPrevious(aMessageOrNil)
1015 	Sets the previous message in the message chain to a deep copy of
1016 	aMessage or it removes the previous message if aMessage is Nil.
1017 	*/
1018 
1019 	IoObject *v = IoMessage_locals_valueArgAt_(m , locals, 0);
1020 	IOASSERT(ISMESSAGE(v) || ISNIL(v), "argument must be Message or Nil");
1021 
1022 	if (ISNIL(v))
1023 	{
1024 		v = NULL;
1025 	}
1026 
1027 	IoMessage_rawSetPrevious(self, v);
1028 
1029 	return self;
1030 }
1031 
IoMessage_rawSetPrevious(IoMessage * self,IoMessage * m)1032 void IoMessage_rawSetPrevious(IoMessage *self, IoMessage *m)
1033 {
1034 #ifdef IOMESSAGE_HASPREV
1035 	DATA(self)->previous = m ? IOREF(m) : NULL;
1036 
1037 	if(m)
1038 	{
1039 		DATA(m)->next = self;
1040 	}
1041 #endif
1042 }
1043 
1044 // ------------------------------------------------------
1045 
IO_METHOD(IoMessage,argAt)1046 IO_METHOD(IoMessage, argAt)
1047 {
1048 	/*doc Message argAt(indexNumber)
1049 	Returns Message object for the specified argument or Nil if none exists.
1050 	*/
1051 
1052 	int index =  IoNumber_asInt(IoMessage_locals_numberArgAt_(m , locals, 0));
1053 	IoObject *v = List_at_(DATA(self)->args, index);
1054 	return v ? v : IONIL(self);
1055 }
1056 
IO_METHOD(IoMessage,arguments)1057 IO_METHOD(IoMessage, arguments)
1058 {
1059 	/*doc Message arguments
1060 	Returns a list of the message objects that act as the
1061 	receiver's arguments. Modifying this list will not alter the actual
1062 	list of arguments. Use the arguments_() method to do that.
1063 	*/
1064 
1065 	IoList *argsList = IoList_new(IOSTATE);
1066 	IoList_rawAddBaseList_(argsList, DATA(self)->args);
1067 	return argsList;
1068 }
1069 
IO_METHOD(IoMessage,setArguments)1070 IO_METHOD(IoMessage, setArguments)
1071 {
1072 	/*doc Message setArguments(aListOfMessages)
1073 	Sets the arguments of the receiver to deep copies of
1074 	those contained in aListOfMessages.  Returns self.
1075 	*/
1076 
1077 	IoList *ioList = IoMessage_locals_listArgAt_(m, locals, 0);
1078 	List *newArgs = IoList_rawList(ioList);
1079 
1080 	List_removeAll(DATA(self)->args);
1081 
1082 	LIST_FOREACH(newArgs, i, argMessage,
1083 
1084 		if (!ISMESSAGE((IoMessage *)argMessage))
1085 		{
1086 			IoState_error_(IOSTATE, m, "arguments_() takes a list containing only Message objects");
1087 		}
1088 
1089 		List_append_(DATA(self)->args, IOREF((IoMessage *)argMessage));
1090 	);
1091 
1092 	return self;
1093 }
1094 
IO_METHOD(IoMessage,appendArg)1095 IO_METHOD(IoMessage, appendArg)
1096 {
1097 /*doc Message appendArg(aMessage)
1098 Adds aMessage to the argument list of receiver. Examples:
1099 <pre>
1100 Io> message(a) appendArg(message(b))
1101 ==> a(b)
1102 
1103 Io> message(a(1,2)) appendArg(message(3))
1104 ==> a(1, 2, 3)
1105 </pre>
1106 */
1107 
1108 	IoMessage *msg = IoMessage_locals_messageArgAt_(m, locals, 0);
1109 	IoMessage_addArg_(self, msg);
1110 	return self;
1111 }
1112 
IO_METHOD(IoMessage,appendCachedArg)1113 IO_METHOD(IoMessage, appendCachedArg)
1114 {
1115 	/*doc Message appendCachedArg(aValue)
1116 	Adds aValue to the argument list of receiver as a cachedResult.
1117 	*/
1118 
1119 	IoObject *v = IoMessage_locals_valueArgAt_(m, locals, 0);
1120 	IoMessage_addCachedArg_(self, v);
1121 	return self;
1122 }
1123 
IO_METHOD(IoMessage,argCount_)1124 IO_METHOD(IoMessage, argCount_)
1125 {
1126 /*doc Message argCount
1127 Returns the number of arguments this message has. A faster way to do, msg arguments size. Examples,
1128 <pre>
1129 Io> message(a(1,2,3)) argCount
1130 ==> 3
1131 
1132 Io> message(a) argCount
1133 ==> 0
1134 </pre>
1135 */
1136 
1137 	return IONUMBER(IoMessage_argCount(self));
1138 }
1139 
IO_METHOD(IoMessage,fromString)1140 IO_METHOD(IoMessage, fromString)
1141 {
1142 	/*doc Message fromString(aString)
1143 	Returns a new Message object for the compiled(but not executed)
1144 	result of aString.
1145 	*/
1146 
1147 	IoSymbol *string = IoMessage_locals_symbolArgAt_(m, locals, 0);
1148 	IoSymbol *label = DATA(m)->label;
1149 
1150 	if (IoMessage_argCount(m) > 1)
1151 	{
1152 		label = IoMessage_locals_symbolArgAt_(m, locals, 1);
1153 	}
1154 
1155 	return IoMessage_newFromText_labelSymbol_(IOSTATE, CSTRING(string), label);
1156 }
1157 
IO_METHOD(IoMessage,cachedResult)1158 IO_METHOD(IoMessage, cachedResult)
1159 {
1160 	/*doc Message cachedResult
1161 	Returns the cached result of the Message or Nil if there is none.
1162 	*/
1163 
1164 	return (DATA(self)->cachedResult ? DATA(self)->cachedResult : IONIL(self));
1165 }
1166 
IO_METHOD(IoMessage,setCachedResult)1167 IO_METHOD(IoMessage, setCachedResult)
1168 {
1169 	/*doc Message setCachedResult(anObject)
1170 	Sets the cached result of the message. Returns self.
1171 	*/
1172 	IoObject *v = IoMessage_locals_valueArgAt_(m , locals, 0);
1173 	IoMessage_rawSetCachedResult_(self, v);
1174 	return self;
1175 }
1176 
IO_METHOD(IoMessage,removeCachedResult)1177 IO_METHOD(IoMessage, removeCachedResult)
1178 {
1179 	/*doc Message removeCachedResult
1180 	Removes the cached result of the Message.
1181 	*/
1182 	IoMessage_rawSetCachedResult_(self, 0x0);
1183 	return self;
1184 }
1185 
IO_METHOD(IoMessage,hasCachedResult)1186 IO_METHOD(IoMessage, hasCachedResult)
1187 {
1188 	/*doc Message hasCachedResult
1189 	Returns true if there is a cached result. Nil is a valid cached result.
1190 	*/
1191 
1192 	return IOBOOL(self,
1193 		IoMessage_rawCachedResult(self) != NULL
1194 	);
1195 }
1196 
IO_METHOD(IoMessage,argsEvaluatedIn)1197 IO_METHOD(IoMessage, argsEvaluatedIn)
1198 {
1199 	/*doc Message argsEvaluatedIn(anObject)
1200 	Returns a List containing the argument messages evaluated in the
1201 	context of anObject.
1202 	*/
1203 
1204 	IoObject *context = IoMessage_locals_valueArgAt_(m, locals, 0);
1205 	IoList *args = IoList_new(IOSTATE);
1206 	int i;
1207 
1208 	for (i = 0; i < List_size(DATA(self)->args); i ++)
1209 	{
1210 		IoObject *arg = IoMessage_locals_valueArgAt_(self, context, i);
1211 		IoList_rawAppend_(args, arg);
1212 	}
1213 	return args;
1214 }
1215 
IO_METHOD(IoMessage,evaluatedArgs)1216 IO_METHOD(IoMessage, evaluatedArgs)
1217 {
1218 	/*doc Message evaluatedArgs
1219 	Returns a List containing the argument messages evaluated in the context.
1220 	*/
1221 
1222 	IoList *args = IoList_new(IOSTATE);
1223 	int i;
1224 
1225 	for (i = 0; i < List_size(DATA(self)->args); i ++)
1226 	{
1227 		IoObject *arg = IoMessage_locals_valueArgAt_(self, locals, i);
1228 		IoList_rawAppend_(args, arg);
1229 	}
1230 
1231 	return args;
1232 }
1233 
1234 // ------------------------------
1235 
1236 /*
1237 IoSymbol *IoMessage_name(IoMessage *self)
1238 {
1239 	return DATA(self)->name;
1240 }
1241 */
1242 
IoMessage_rawLabel(IoMessage * self)1243 IoSymbol *IoMessage_rawLabel(IoMessage *self)
1244 {
1245 	return DATA(self)->label;
1246 }
1247 
IoMessage_rawArgs(IoMessage * self)1248 List *IoMessage_rawArgs(IoMessage *self)
1249 {
1250 	return DATA(self)->args;
1251 }
1252 
IoMessage_rawArgAt_(IoMessage * self,int n)1253 IoMessage *IoMessage_rawArgAt_(IoMessage *self, int n)
1254 {
1255 	IoMessage *result = List_at_(DATA(self)->args, n);
1256 	IoState_stackRetain_(IOSTATE, result);
1257 	return result;
1258 }
1259 
IoMessage_addArg_(IoMessage * self,IoMessage * m)1260 void IoMessage_addArg_(IoMessage *self, IoMessage *m)
1261 {
1262 	List_append_(DATA(self)->args, IOREF(m));
1263 }
1264 
1265 // -------------------------------
1266 
IoMessage_asMinimalStackEntryDescription(IoMessage * self)1267 UArray *IoMessage_asMinimalStackEntryDescription(IoMessage *self)
1268 {
1269 	IoSymbol *name = IoMessage_name(self);
1270 	IoSymbol *label = IoMessage_rawLabel(self);
1271 	int lineNumber = IoMessage_rawLineNumber(self);
1272 	return UArray_newWithFormat_("%s:%i %s", CSTRING(label), lineNumber, CSTRING(name));
1273 }
1274 
IoMessage_foreachArgs(IoMessage * self,IoObject * receiver,IoSymbol ** indexSlotName,IoSymbol ** valueSlotName,IoMessage ** doMessage)1275 void IoMessage_foreachArgs(IoMessage *self,
1276 						   IoObject *receiver,
1277 						   IoSymbol **indexSlotName,
1278 						   IoSymbol **valueSlotName,
1279 						   IoMessage **doMessage)
1280 {
1281 	int offset;
1282 
1283 	IoMessage_assertArgCount_receiver_(self, 2, receiver);
1284 
1285 	if (IoMessage_argCount(self) > 2)
1286 	{
1287 		*indexSlotName = IoMessage_name(IoMessage_rawArgAt_(self, 0));
1288 		offset = 1;
1289 	}
1290 	else
1291 	{
1292 		*indexSlotName = NULL; //IONIL(self);
1293 		offset = 0;
1294 	}
1295 
1296 	*valueSlotName = IoMessage_name(IoMessage_rawArgAt_(self, 0 + offset));
1297 	*doMessage = IoMessage_rawArgAt_(self, 1 + offset);
1298 }
1299 
IoMessage_asMessageWithEvaluatedArgs(IoMessage * self,IoObject * locals,IoMessage * m)1300 IoMessage *IoMessage_asMessageWithEvaluatedArgs(IoMessage *self, IoObject *locals, IoMessage *m)
1301 {
1302   /*doc Message asMessageWithEvaluatedArgs(optionalContext)
1303 	Returns a copy of receiver with arguments evaluated in the context of sender if
1304 	optionalContext is nil.
1305 	*/
1306 	IoState *state = IOSTATE;
1307 	IoMessage *sendMessage;
1308 	int i, max = IoMessage_argCount(self);
1309 	IoObject *context = locals;
1310 
1311 	if (IoMessage_argCount(m) > 0)
1312 	{
1313 		context = IoMessage_locals_valueArgAt_(m, locals, 0);
1314 	}
1315 
1316 	if (!IoMessage_needsEvaluation(self))
1317 	{
1318 		return self;
1319 	}
1320 
1321 	sendMessage = IoMessage_newWithName_(state, IoMessage_name(self));
1322 	for (i = 0; i < max; i ++)
1323 	{
1324 		IoMessage *arg = IoMessage_rawArgAt_(self, i);
1325 		IoObject *result = IoMessage_locals_performOn_(arg, context, context);
1326 		IoMessage_setCachedArg_to_(sendMessage, i, result);
1327 	}
1328 
1329 	return sendMessage;
1330 }
1331 
1332