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