8 #ifdef SYMBOL_DISPATCH_
17 #if PTRDIFF_MAX < INT_MAX
18 #define TAGGED_INT_MAX (PTRDIFF_MAX >> 1)
19 #define TAGGED_INT_MIN (PTRDIFF_MIN >> 1)
21 #define TAGGED_INT_MAX (INT_MAX >> 1)
22 #define TAGGED_INT_MIN (INT_MIN >> 1)
26 #ifdef SYMBOL_DISPATCH_
27 // Not thread-safe! We'll need to move this to thread-local storage if we
29 static obj_ unhandledMessage
= nil
;
32 static obj_
SendMessageNotUnderstood_(obj_ object
, ...);
35 fn_ptr_
Dispatch_(dispatch_selector_ selectorIn
, obj_ object
)
39 object
= &nil__Standard
;
41 #if defined(NIL_OBJECT_) && defined(TAGGED_INTS_)
45 if (IsTaggedInt_(object
))
46 object
= &SmallInt__CImplementation__Standard
;
49 #ifdef SYMBOL_DISPATCH_
51 ((struct Standard__Symbol__internal
*) selectorIn
)->selector
;
53 int selector
= selectorIn
;
56 // First, try to get it from the dispatch table.
57 struct RDTableEntry_
* entry
=
58 &dispatchTable_
[selector
+ ClassNumFor_(object
)];
59 if (entry
->selector
== selector
)
62 #if defined(SUPPORT_NEW_METHODS_) && defined(SYMBOL_DISPATCH_)
63 // Next, try the "newMethods" dictionaries for this and all superclasses, and
64 // the dispatch tables of the superclasses too.
65 struct ClassInfo
* classInfo
= object
->class_
;
67 if (classInfo
->newMethods
) {
69 obj_ method_ptr
= Call_(at_co_
, classInfo
->newMethods
, selectorIn
);
71 return (fn_ptr_
) BytePtrValue_(method_ptr
);
73 if (classInfo
->superclass
== nil
)
75 classInfo
= classInfo
->superclass
->class_
;
76 entry
= &dispatchTable_
[selector
+ classInfo
->classNum
];
77 if (entry
->selector
== selector
)
82 // Message not understood.
83 // Send 'message-not-understood:arguments:' instead.
84 #ifdef SYMBOL_DISPATCH_
85 unhandledMessage
= selectorIn
;
87 return (fn_ptr_
) &SendMessageNotUnderstood_
;
91 obj_
RespondsTo_(obj_ object
, dispatch_selector_ selectorIn
)
95 object
= &nil__Standard
;
97 #if defined(NIL_OBJECT_) && defined(TAGGED_INTS_)
101 if (IsTaggedInt_(object
))
102 object
= &SmallInt__CImplementation__Standard
;
105 #ifdef SYMBOL_DISPATCH_
107 ((struct Standard__Symbol__internal
*) selectorIn
)->selector
;
109 selector_ selector
= selectorIn
;
112 // First, try the dispatch table.
113 struct RDTableEntry_
* entry
=
114 &dispatchTable_
[selector
+ ClassNumFor_(object
)];
115 if (entry
->selector
== selector
)
118 #if defined(SUPPORT_NEW_METHODS_) && defined(SYMBOL_DISPATCH_)
119 // Next, try the "newMethods" dictionaries for this and all superclasses, and
120 // the dispatch tables of the superclasses too.
121 struct ClassInfo
* classInfo
= object
->class_
;
123 if (classInfo
->newMethods
) {
125 obj_ method_ptr
= Call_(at_co_
, classInfo
->newMethods
, selectorIn
);
129 if (classInfo
->superclass
== nil
)
131 classInfo
= classInfo
->superclass
->class_
;
132 entry
= &dispatchTable_
[selector
+ classInfo
->classNum
];
133 if (entry
->selector
== selector
)
142 #ifdef SUPPORT_NEW_METHODS_
143 fn_ptr_
* MethodLocation_(obj_ object
, dispatch_selector_ selectorIn
)
147 object
= &nil__Standard
;
149 #if defined(NIL_OBJECT_) && defined(TAGGED_INTS_)
153 if (IsTaggedInt_(object
))
154 object
= &SmallInt__CImplementation__Standard
;
157 #ifdef SYMBOL_DISPATCH_
159 ((struct Standard__Symbol__internal
*) selectorIn
)->selector
;
161 selector_ selector
= selectorIn
;
164 struct RDTableEntry_
* entry
=
165 &dispatchTable_
[selector
+ ClassNumFor_(object
)];
167 if (entry
->selector
== selector
)
168 return &entry
->method
;
175 static obj_
SendMessageNotUnderstood_(obj_ object
, ...)
177 #ifdef SYMBOL_DISPATCH_
179 UsingMethod_(characters
) UsingMethod_(iterator
)
180 UsingMethod_(is_done
) UsingMethod_(current_item
) UsingMethod_(go_forward
)
181 UsingMethod_(message_not_understood_co_arguments_co_
);
182 int num_args
= 0, which_arg
;
187 // How many arguments are there?
188 // We can find out by counting the number of colons in the selector.
189 obj_ characters
= Call_(characters
, unhandledMessage
);
190 ForStart_(1, characters
, char_obj
)
191 c
= IntValue_(char_obj
);
196 // Gather the arguments into a tuple.
197 args_tuple
= NewTuple_(num_args
);
198 va_start(arg_list
, object
);
199 for (which_arg
= 0; which_arg
< num_args
; ++which_arg
) {
200 obj_ arg
= va_arg(arg_list
, obj_
);
201 TuplePut_(args_tuple
, which_arg
, arg
);
205 // Call 'message-not-understood:arguments:'.
208 message_not_understood_co_arguments_co_
,
209 object
, unhandledMessage
, args_tuple
);
211 #else // !SYMBOL_DISPATCH_
213 // If 'symbol-dispatch' isn't on, we don't have a good way of knowing what
215 UsingMethod_(message_not_understood
);
216 return Call_(message_not_understood
, object
);
222 obj_
AllocObjFromClassInfo_(struct ClassInfo
* classInfo
)
226 sizeof(classref_
) + classInfo
->numSlots
* sizeof(obj_
));
227 object
->class_
= classInfo
;
232 static ExceptionCatcher_
* currentExceptionCatcher
= NULL
;
233 obj_ currentException_
= NULL
;
235 void PushException_(ExceptionCatcher_
* catcher
)
237 catcher
->nextCatcher
= currentExceptionCatcher
;
238 currentExceptionCatcher
= catcher
;
242 void Throw_(obj_ object
)
244 if (currentExceptionCatcher
== NULL
) {
245 // Catastrophic failure!
246 printf("\n**** Uncaught exception! ****\n\n");
250 currentException_
= object
;
251 longjmp(currentExceptionCatcher
->jumpBuf
, 1);
257 if (currentExceptionCatcher
== NULL
) {
258 // Catastrophic failure, and it's probably the compiler's fault!
259 printf("\n**** Compiler error: generated bad _PopException_()! ***\n\n");
263 currentExceptionCatcher
= currentExceptionCatcher
->nextCatcher
;
267 static void FinalizeObject_(void* obj
, void* clientData
)
269 UsingMethod_(destroy
);
270 Call_(destroy
, (obj_
) obj
);
274 void RegisterFinalizer_(obj_ object
)
276 GC_finalization_proc oldProc
;
278 GC_REGISTER_FINALIZER(object
, &FinalizeObject_
, NULL
, &oldProc
, &oldData
);
284 int IntValue_(obj_ obj
)
286 if (((ptrdiff_t) obj
& 0x01) != 0)
287 return (ptrdiff_t) obj
>> 1;
288 return (((struct Standard__Int__internal
*) obj
)->value
);
293 obj_
BuildInt_(int value
)
296 if (value
<= TAGGED_INT_MAX
&& value
>= TAGGED_INT_MIN
)
297 return SmallInt_(value
);
300 struct Standard__Int__internal
* result
=
301 (struct Standard__Int__internal
*)
302 GC_MALLOC(sizeof(struct Standard__Int__internal
));
303 result
->class_
= StdClassRef_(Int
);
304 result
->value
= value
;
305 return (obj_
) result
;
309 obj_
BuildFloat_(double value
)
311 struct Standard__Float__internal
* result
=
312 (struct Standard__Float__internal
*)
313 GC_MALLOC(sizeof(struct Standard__Float__internal
));
314 result
->class_
= StdClassRef_(Float
);
315 result
->value
= value
;
316 return (obj_
) result
;
320 obj_
BuildBytePtr_(void* value
)
322 struct Standard__BytePtr__internal
* result
=
323 (struct Standard__BytePtr__internal
*)
324 GC_MALLOC(sizeof(struct Standard__BytePtr__internal
));
325 result
->class_
= StdClassRef_(BytePtr
);
326 result
->value
= value
;
327 return (obj_
) result
;
331 obj_
BuildString_(const char* cString
)
336 struct Standard__String__internal
* strObj
;
338 // Copy the string to the heap.
339 length
= strlen(cString
);
340 heapString
= (char*) GC_MALLOC_ATOMIC(length
+ 1);
341 memcpy(heapString
, cString
, length
+ 1);
343 // Build the string object.
345 (struct Standard__String__internal
*)
346 GC_MALLOC(sizeof(struct Standard__String__internal
));
347 strObj
->class_
= StdClassRef_(String
);
348 strObj
->start
= BuildBytePtr_((byte_ptr_
) heapString
);
349 strObj
->stopper
= BuildBytePtr_((byte_ptr_
) heapString
+ length
);
350 return (obj_
) strObj
;
354 obj_
BuildStringOfLength_(const char* cString
, unsigned int length
)
357 struct Standard__String__internal
* strObj
;
359 // Copy the string to the heap.
360 heapString
= (char*) GC_MALLOC(length
+ 1);
361 memcpy(heapString
, cString
, length
+ 1);
363 // Build the string object.
365 (struct Standard__String__internal
*)
366 GC_MALLOC(sizeof(struct Standard__String__internal
));
367 strObj
->class_
= StdClassRef_(String
);
368 strObj
->start
= BuildBytePtr_((byte_ptr_
) heapString
);
369 strObj
->stopper
= BuildBytePtr_((byte_ptr_
) heapString
+ length
);
370 return (obj_
) strObj
;
374 obj_
BuildStringStartStopper_(const char* start
, const char* stopper
)
376 struct Standard__String__internal
* strObj
;
378 // Build the string object.
380 (struct Standard__String__internal
*)
381 GC_MALLOC(sizeof(struct Standard__String__internal
));
382 strObj
->class_
= StdClassRef_(String
);
383 strObj
->start
= BuildBytePtr_((byte_ptr_
) start
);
384 strObj
->stopper
= BuildBytePtr_((byte_ptr_
) stopper
);
385 return (obj_
) strObj
;
389 char* CString_(obj_ str
)
391 struct Standard__String__internal
* strObj
=
392 (struct Standard__String__internal
*) str
;
397 start
= StringStart_(strObj
);
398 length
= StringStopper_(strObj
) - start
;
399 cString
= GC_MALLOC_ATOMIC(length
+ 1);
400 memcpy(cString
, start
, length
);
406 void* Allocate_(int numBytes
)
408 return GC_MALLOC(numBytes
);
412 void* AllocNonPtr_(int numBytes
)
414 return GC_MALLOC_ATOMIC(numBytes
);
418 obj_
NewTuple_(int numItems
)
420 extern obj_
new_co___Tuple__Standard(obj_
, obj_
);
421 return new_co___Tuple__Standard(Proto_(Tuple__Standard
), BuildInt_(numItems
));
425 obj_
TupleAt_(obj_ tuple
, int index
)
427 return tuple
->fields
[index
+ 1];
431 void TuplePut_(obj_ tuple
, int index
, obj_ value
)
433 tuple
->fields
[index
+ 1] = value
;
437 obj_
CloneObj_(obj_ object
)
439 return AllocObjFromClassInfo_(object
->class_
);
443 obj_
CloneObjExtra_(obj_ object
, int numExtraFields
)
447 (object
->class_
->numSlots
+ numExtraFields
) * sizeof(obj_
);
448 obj_ newObject
= (obj_
) GC_MALLOC(size
);
449 newObject
->class_
= object
->class_
;
455 obj_ symbol
, const EnumDictEntry_
* dict
, int dictSize
, int notFoundValue
)
457 /* The dictionary is sorted by symbol name, and the symbol objects are sorted
458 in memory, so we can use a binary search. */
459 unsigned int low
= 0;
460 unsigned int high
= dictSize
- 1;
461 while (low
<= high
) {
462 unsigned int mid
= (low
+ high
) / 2;
463 const EnumDictEntry_
* entry
= &dict
[mid
];
464 if (entry
->symbol
> symbol
)
466 else if (entry
->symbol
< symbol
)
473 return notFoundValue
;
477 int BitFlagsFromSyms_(obj_ symbols
, const EnumDictEntry_
* dict
, int dictSize
)
481 ForStart_(1, symbols
, symbol
)
482 flags
|= SymToEnum_(symbol
, dict
, dictSize
, 0);
489 obj_
EnumToSym_(int value
, const EnumDictEntry_
* dict
, int dictSize
)
492 const EnumDictEntry_
* entry
= dict
;
493 const EnumDictEntry_
* stopper
= &dict
[dictSize
];
494 for (; entry
< stopper
; ++entry
) {
495 if (entry
->value
== value
)
496 return entry
->symbol
;
503 int main(int argc
, char* argv
[])
507 extern obj_
main_co___Main(obj_ this_
, obj_ args
);
508 extern obj_
new__List__Standard(obj_ this_
);
509 UsingMethod_(append_co_
)
510 UsingClass_(Main
) UsingClass_(List__Standard
)
514 // Build the list of args.
515 args
= new__List__Standard(Proto_(List__Standard
));
516 for (whichArg
= 0; whichArg
< argc
; ++whichArg
)
517 Call_(append_co_
, args
, BuildString_(argv
[whichArg
]));
519 // Call the main function.
521 result
= main_co___Main(Proto_(Main
), args
);
524 UsingMethod_(send_co_
) UsingMethod_(message
)
525 obj_ message
= Call_(message
, exception
);
526 Call_(send_co_
, Proto_(Standard
), message
);
527 result
= BuildInt_(1);
531 // Return the result.
535 else if (IsTaggedInt_(result
))
536 return IntValue_(result
);
538 else if (result
->class_
== StdClassRef_(Int
))
539 return IntValue_(result
);
548 const char* className_(obj_ object
)
553 return StringStart_(object
->class_
->name
);
557 obj_
showObj_(obj_ object
)
560 UsingMethod_(debug_write
)
565 str
= Call_(debug_write
, object
);
572 Copyright 2005 - 2007 Steve Folta.
573 See the License file.