removed send_message_with_str(), find_method_with_str()

registered some commonly used method names as symbols - doesNotUnderstand:, unwindTo:return:, primitiveFailed
invocation of the above methods doesn't need send_message_with_str()
changed startup method invocation to look up for a symbol first instead of using the above functions removed
This commit is contained in:
hyunghwan.chung 2019-06-23 04:49:38 +00:00
parent ae20171772
commit 3419097054
5 changed files with 124 additions and 155 deletions

View File

@ -8,6 +8,53 @@
class MyObject(Object) class MyObject(Object)
{ {
var(#class) a := 100. var(#class) a := 100.
var(#class) ensure_tester_v := 0.
method(#class) test_quicksort: anArray
{
| quicksort |
quicksort := nil.
quicksort := [ :data :from :to |
(from < to)
ifTrue: [ | pivot index |
pivot := data at: from.
data swap: from with: to.
index := from.
from to: (to - 1) do: [ :each |
(data at: each) < pivot
ifTrue: [
data swap: each with: index.
index := index + 1
]
].
data swap: to with: index.
quicksort value: data value: from value: index - 1.
quicksort value: data value: index + 1 value: to
].
data
].
^(quicksort value: anArray value: 0 value: (anArray size - 1))
}
method(#class) test_on_do_with: dividend with: divisor
{
## it returns 0 upon an exception otherwise, division result.
^[ dividend div: divisor ] on: Exception do: [:ex | 0 ]
}
method(#class) test_ensure_with: v
{
[
[ Exception signal: "test ensure exception" ] ensure: [ self.ensure_tester_v := v ].
] on: Exception do: [:ex | /* do nothing */ ].
}
method(#class) test_ensure2_with: v
{
[ ^v * v ] ensure: [ self.ensure_tester_v := v ].
}
method(#class) proc1 method(#class) proc1
{ {
@ -103,48 +150,27 @@ class MyObject(Object)
} }
*/ */
method(#class) test_quicksort: anArray
{
| quicksort |
quicksort := nil.
quicksort := [ :data :from :to |
(from < to)
ifTrue: [ | pivot index |
pivot := data at: from.
data swap: from with: to.
index := from.
from to: (to - 1) do: [ :each |
(data at: each) < pivot
ifTrue: [
data swap: each with: index.
index := index + 1
]
].
data swap: to with: index.
quicksort value: data value: from value: index - 1.
quicksort value: data value: index + 1 value: to
].
data
].
^(quicksort value: anArray value: 0 value: (anArray size - 1))
}
method(#class) main method(#class) main
{ {
| tc limit | | tc limit |
tc := %( tc := %(
## 0 - 4 ## 0 - 4
[ (self test_quicksort: #(7 12 3 20 5 8 2) copy) = #(2 3 5 7 8 12 20)],
[ (self test_quicksort: %(99, 12, 18, 7, 12, 3, 20, 5, 8, 2)) = #(2 3 5 7 8 12 12 18 20 99)],
[ (self test_on_do_with: 10 with: 2) == 5 ],
[ (self test_on_do_with: -10 with: 0) == 0 ],
[ self test_ensure_with: -20945. self.ensure_tester_v == -20945 ],
## 5-9
[ ((self test_ensure2_with: 8) == 64) and: [self.ensure_tester_v == 8] ],
[ self proc1 == 100 ], [ self proc1 == 100 ],
[ System sleepForSecs: 2. self proc1 == 200 ], [ System sleepForSecs: 2. self proc1 == 200 ],
[ self test_semaphore_heap == true ], [ self test_semaphore_heap == true ],
[ self test_mutex = #(2000 6000) ], [ self test_mutex = #(2000 6000) ],
####[ self test_sem_sig ],
[ (self test_quicksort: #(7 12 3 20 5 8 2) copy) = #(2 3 5 7 8 12 20)],
[ (self test_quicksort: %(99, 12, 18, 7, 12, 3, 20, 5, 8, 2)) = #(2 3 5 7 8 12 12 18 20 99)],
## 10-14
####[ self test_sem_sig ],
[ System sleepForSecs: 2. self.a == 300 ] ## sleep before checking self.a to prevent different result depending on process switching frequency and speed [ System sleepForSecs: 2. self.a == 300 ] ## sleep before checking self.a to prevent different result depending on process switching frequency and speed
). ).

View File

@ -136,7 +136,6 @@ static MOO_INLINE const char* proc_state_to_string (int state)
static int delete_sem_from_sem_io_tuple (moo_t* moo, moo_oop_semaphore_t sem, int force); static int delete_sem_from_sem_io_tuple (moo_t* moo, moo_oop_semaphore_t sem, int force);
static void signal_io_semaphore (moo_t* moo, moo_ooi_t io_handle, moo_ooi_t mask); static void signal_io_semaphore (moo_t* moo, moo_ooi_t io_handle, moo_ooi_t mask);
static int send_message (moo_t* moo, moo_oop_char_t selector, moo_ooi_t nargs, int to_super); static int send_message (moo_t* moo, moo_oop_char_t selector, moo_ooi_t nargs, int to_super);
static int send_message_with_str (moo_t* moo, const moo_ooch_t* nameptr, moo_oow_t namelen, moo_ooi_t nargs);
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
static MOO_INLINE int vm_startup (moo_t* moo) static MOO_INLINE int vm_startup (moo_t* moo)
@ -1686,58 +1685,6 @@ moo_oop_method_t moo_findmethodinclasschain (moo_t* moo, moo_oop_class_t _class,
return mth; return mth;
} }
static MOO_INLINE moo_oop_method_t find_method_with_str (moo_t* moo, moo_oop_t receiver, const moo_oocs_t* message, int in_super)
{
/* this function should be the same as moo_findmethod() mostly except cache management.
* this function can get removed if the callers create a symbol before look-up. TODO: << */
moo_oop_class_t _class;
moo_oop_class_t c;
int mth_type;
moo_oop_method_t mth;
_class = MOO_CLASSOF(moo, receiver);
if (_class == moo->_class)
{
/* receiver is a class object (an instance of Class) */
c = (moo_oop_class_t)receiver;
mth_type = MOO_METHOD_CLASS;
}
else
{
/* receiver is not a class object. so take its class */
c = _class;
mth_type = MOO_METHOD_INSTANCE;
}
MOO_ASSERT (moo, (moo_oop_t)c != moo->_nil);
if (in_super)
{
MOO_ASSERT (moo, moo->active_method);
MOO_ASSERT (moo, moo->active_method->owner);
c = (moo_oop_class_t)((moo_oop_class_t)moo->active_method->owner)->superclass;
if ((moo_oop_t)c == moo->_nil) goto not_found;
/* c is nil if it reached the top of the hierarchy.
* otherwise c points to a class object */
}
/* [IMPORT] the method lookup logic should be the same as ciim_on_each_method() in comp.c */
mth = find_method_in_class_chain(moo, c, mth_type, message);
if (mth) return mth;
not_found:
if (_class == moo->_class)
{
/* the object is an instance of Class. find the method
* in an instance method dictionary of Class also */
mth = find_method_in_class(moo, _class, MOO_METHOD_INSTANCE, message);
if (mth) return mth;
}
MOO_LOG3 (moo, MOO_LOG_DEBUG, "Method '%.*js' not found in receiver %O\n", message->len, message->ptr, receiver);
moo_seterrbfmt (moo, MOO_ENOENT, "unable to find the method '%.*js' in %O", message->len, message->ptr, receiver);
return MOO_NULL;
}
moo_oop_method_t moo_findmethod (moo_t* moo, moo_oop_t receiver, moo_oop_char_t selector, int in_super) moo_oop_method_t moo_findmethod (moo_t* moo, moo_oop_t receiver, moo_oop_char_t selector, int in_super)
{ {
moo_oop_class_t _class; moo_oop_class_t _class;
@ -1836,8 +1783,8 @@ not_found:
} }
} }
MOO_LOG3 (moo, MOO_LOG_DEBUG, "Method '%.*js' not found in receiver %O\n", message.len, message.ptr, receiver); MOO_LOG4 (moo, MOO_LOG_DEBUG, "Method '%O>>%.*js' not found in receiver %O\n", _class, message.len, message.ptr, receiver);
moo_seterrbfmt (moo, MOO_ENOENT, "unable to find the method '%.*js' in %O", message.len, message.ptr, receiver); moo_seterrbfmt (moo, MOO_ENOENT, "unable to find the method '%O>>%.*js' in %O", _class, message.len, message.ptr, receiver);
return MOO_NULL; return MOO_NULL;
} }
@ -1858,29 +1805,38 @@ static int start_initial_process_and_context (moo_t* moo, const moo_oocs_t* objn
moo_oop_context_t ctx; moo_oop_context_t ctx;
moo_oop_method_t mth; moo_oop_method_t mth;
moo_oop_process_t proc; moo_oop_process_t proc;
moo_oow_t tmp_count = 0;
moo_oop_t sym_startup;
#if defined(INVOKE_DIRECTLY) #if defined(INVOKE_DIRECTLY)
moo_oop_association_t ass; moo_oop_association_t ass;
#else #else
moo_oop_t s1, s2; moo_oop_t s1, s2;
#endif
moo_oow_t tmp_count = 0;
moo_oocs_t startup;
static moo_ooch_t str_startup[] = { 's', 't', 'a', 'r', 't', 'u', 'p' }; static moo_ooch_t str_startup[] = { 's', 't', 'a', 'r', 't', 'u', 'p' };
#endif
#if defined(INVOKE_DIRECTLY) #if defined(INVOKE_DIRECTLY)
ass = moo_lookupsysdic(moo, objname); ass = moo_lookupsysdic(moo, objname);
if (!ass || MOO_CLASSOF(moo, ass->value) != moo->_class) if (!ass || MOO_CLASSOF(moo, ass->value) != moo->_class)
{ {
MOO_LOG2 (moo, MOO_LOG_DEBUG, "Cannot find a class '%.*js'", objname->len, objname->ptr); MOO_LOG2 (moo, MOO_LOG_DEBUG, "Cannot find a class '%.*js'", objname->len, objname->ptr);
return -1; return -1;
} }
sym_statup = moo_findsymbol(moo, mthname->ptr, mthname->len;
if (!sym_startup)
{
/* the method name should exist as a symbol in the system.
* otherwise, a method of such a name also doesn't exist */
MOO_LOG4 (moo, MOO_LOG_DEBUG, "Cannot find a startup method symbol %.*js>>%.*js", objname->len, objname->ptr, mthname->len, mthname->ptr);
goto oops;
}
mth = moo_findmethowithstr(moo, ass->value, mthname, 0); mth = moo_findmethod(moo, moo, ass->value, sym_startup, 0);
if (!mth) if (!mth)
{ {
MOO_LOG4 (moo, MOO_LOG_DEBUG, "Cannot find a method %.*js>>%.*js", objname->len, objname->ptr, mthname->len, mthname->ptr); MOO_LOG4 (moo, MOO_LOG_DEBUG, "Cannot find a startup method %.*js>>%.*js", objname->len, objname->ptr, mthname->len, mthname->ptr);
return -1; return -1;
} }
@ -1898,9 +1854,16 @@ TODO: overcome this problem - accept parameters....
moo_pushvolat (moo, (moo_oop_t*)&mth); tmp_count++; moo_pushvolat (moo, (moo_oop_t*)&mth); tmp_count++;
moo_pushvolat (moo, (moo_oop_t*)&ass); tmp_count++; moo_pushvolat (moo, (moo_oop_t*)&ass); tmp_count++;
#else #else
startup.ptr = str_startup; sym_startup = moo_findsymbol(moo, str_startup, MOO_COUNTOF(str_startup));
startup.len = 7; if (!sym_startup)
mth = find_method_with_str(moo, (moo_oop_t)moo->_system, &startup, 0); {
/* the method name should exist as a symbol in the system.
* otherwise, a method of such a name also doesn't exist */
MOO_LOG0 (moo, MOO_LOG_DEBUG, "Cannot find the startup method name symbol in the system class");
goto oops;
}
mth = moo_findmethod(moo, (moo_oop_t)moo->_system, (moo_oop_char_t)sym_startup, 0);
if (!mth) if (!mth)
{ {
MOO_LOG0 (moo, MOO_LOG_DEBUG, "Cannot find the startup method in the system class"); MOO_LOG0 (moo, MOO_LOG_DEBUG, "Cannot find the startup method in the system class");
@ -1932,7 +1895,6 @@ TODO: overcome this problem - accept parameters....
moo_pushvolat (moo, (moo_oop_t*)&ctx); tmp_count++; moo_pushvolat (moo, (moo_oop_t*)&ctx); tmp_count++;
/* TODO: handle preamble */ /* TODO: handle preamble */
/* the initial context starts the life of the entire VM /* the initial context starts the life of the entire VM
@ -4402,11 +4364,6 @@ static int start_method (moo_t* moo, moo_oop_method_t method, moo_oow_t nargs)
#endif #endif
{ {
/* no byte code to execute - invoke 'self primitiveFailed' */ /* no byte code to execute - invoke 'self primitiveFailed' */
static moo_ooch_t prim_fail_msg[] = {
'p', 'r', 'i', 'm', 'i', 't', 'i', 'v', 'e',
'F', 'a', 'i', 'l', 'e', 'd'
};
moo_oow_t i; moo_oow_t i;
if (stack_base != moo->sp - nargs - 1) if (stack_base != moo->sp - nargs - 1)
@ -4432,12 +4389,12 @@ static int start_method (moo_t* moo, moo_oop_method_t method, moo_oow_t nargs)
MOO_STACK_SET (moo, stack_base + 2, (moo_oop_t)method); MOO_STACK_SET (moo, stack_base + 2, (moo_oop_t)method);
/* send primitiveFailed to self */ /* send primitiveFailed to self */
if (send_message_with_str (moo, prim_fail_msg, 15, nargs + 1) <= -1) return -1; if (send_message(moo, moo->primitive_failed_sym, nargs + 1, 0) <= -1) return -1;
} }
else else
{ {
/* arrange to execute the method body */ /* arrange to execute the method body */
if (activate_new_method (moo, method, nargs) <= -1) return -1; if (activate_new_method(moo, method, nargs) <= -1) return -1;
} }
break; break;
} }
@ -4447,7 +4404,7 @@ static int start_method (moo_t* moo, moo_oop_method_t method, moo_oow_t nargs)
preamble_code == MOO_METHOD_PREAMBLE_RETURN_CONTEXT || preamble_code == MOO_METHOD_PREAMBLE_RETURN_CONTEXT ||
preamble_code == MOO_METHOD_PREAMBLE_EXCEPTION || preamble_code == MOO_METHOD_PREAMBLE_EXCEPTION ||
preamble_code == MOO_METHOD_PREAMBLE_ENSURE); preamble_code == MOO_METHOD_PREAMBLE_ENSURE);
if (activate_new_method (moo, method, nargs) <= -1) return -1; if (activate_new_method(moo, method, nargs) <= -1) return -1;
break; break;
} }
@ -4468,27 +4425,18 @@ static int send_message (moo_t* moo, moo_oop_char_t selector, moo_ooi_t nargs, i
method = moo_findmethod(moo, receiver, selector, to_super); method = moo_findmethod(moo, receiver, selector, to_super);
if (!method) if (!method)
{ {
static moo_ooch_t fbm[] = { method = moo_findmethod(moo, receiver, moo->does_not_understand_sym, 0);
'd', 'o', 'e', 's',
'N', 'o', 't',
'U', 'n', 'd', 'e', 'r', 's', 't', 'a', 'n', 'd', ':'
};
moo_oocs_t mthname;
mthname.ptr = fbm;
mthname.len = 18;
method = find_method_with_str(moo, receiver, &mthname, 0);
if (!method) if (!method)
{ {
/* this must not happen as long as doesNotUnderstand: is implemented under Apex. /* this must not happen as long as doesNotUnderstand: is implemented under Apex.
* this check should indicate a very serious internal problem */ * this check should indicate a very serious internal problem */
MOO_LOG4 (moo, MOO_LOG_IC | MOO_LOG_FATAL, MOO_LOG4 (moo, MOO_LOG_IC | MOO_LOG_FATAL,
"Fatal error - receiver [%O] of class [%O] does not understand a message [%.*js]\n", "Fatal error - unable to find a fallback method [%O<<%.*js] for receiver [%O]\n",
receiver, MOO_CLASSOF(moo, receiver), mthname.len, mthname.ptr); MOO_CLASSOF(moo, receiver), MOO_OBJ_GET_SIZE(moo->does_not_understand_sym), MOO_OBJ_GET_CHAR_SLOT(moo->does_not_understand_sym), receiver);
moo_seterrnum (moo, MOO_EMSGSND); moo_seterrbfmt (moo, MOO_EMSGSND, "unable to find a fallback method - %O<<%.*js",
MOO_CLASSOF(moo, receiver), MOO_OBJ_GET_SIZE(moo->does_not_understand_sym), MOO_OBJ_GET_CHAR_SLOT(moo->does_not_understand_sym));
return -1; return -1;
} }
else else
@ -4503,30 +4451,7 @@ static int send_message (moo_t* moo, moo_oop_char_t selector, moo_ooi_t nargs, i
} }
} }
return start_method (moo, method, nargs); return start_method(moo, method, nargs);
}
static int send_message_with_str (moo_t* moo, const moo_ooch_t* nameptr, moo_oow_t namelen, moo_ooi_t nargs)
{
moo_oocs_t mthname;
moo_oop_t receiver;
moo_oop_method_t method;
receiver = MOO_STACK_GET(moo, moo->sp - nargs);
mthname.ptr = (moo_ooch_t*)nameptr;
mthname.len = namelen;
method = find_method_with_str(moo, receiver, &mthname, 0);
if (!method)
{
MOO_LOG4 (moo, MOO_LOG_IC | MOO_LOG_FATAL,
"Fatal error - receiver [%O] of class [%O] does not understand a private message [%.*js]\n",
receiver, MOO_CLASSOF(moo, receiver), mthname.len, mthname.ptr);
moo_seterrnum (moo, MOO_EMSGSND);
return -1;
}
return start_method (moo, method, nargs);
} }
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
@ -4935,16 +4860,12 @@ static MOO_INLINE int do_return (moo_t* moo, moo_oob_t bcode, moo_oop_t return_v
if (unwind_protect) if (unwind_protect)
{ {
static moo_ooch_t fbm[] = { /* if ensure: is used over a non-local return, it should reach here.
'u', 'n', 'w', 'i', 'n', 'd', 'T', 'o', ':', * [^10] ensure: [...] */
'r', 'e', 't', 'u', 'r', 'n', ':'
};
MOO_STACK_PUSH (moo, (moo_oop_t)unwind_start); MOO_STACK_PUSH (moo, (moo_oop_t)unwind_start);
MOO_STACK_PUSH (moo, (moo_oop_t)unwind_stop); MOO_STACK_PUSH (moo, (moo_oop_t)unwind_stop);
MOO_STACK_PUSH (moo, (moo_oop_t)return_value); MOO_STACK_PUSH (moo, (moo_oop_t)return_value);
if (send_message(moo, moo->unwindto_return_sym, 2, 0) <= -1) return -1;
if (send_message_with_str(moo, fbm, 16, 2) <= -1) return -1;
} }
else else
{ {

View File

@ -566,7 +566,10 @@ static int ignite_3 (moo_t* moo)
static moo_ooch_t str_processor[] = { 'P', 'r', 'o', 'c', 'e', 's', 's', 'o', 'r' }; static moo_ooch_t str_processor[] = { 'P', 'r', 'o', 'c', 'e', 's', 's', 'o', 'r' };
static moo_ooch_t str_dicnew[] = { 'n', 'e', 'w', ':' }; static moo_ooch_t str_dicnew[] = { 'n', 'e', 'w', ':' };
static moo_ooch_t str_dicputassoc[] = { '_','_','p', 'u', 't', '_', 'a', 's', 's', 'o', 'c', ':' }; static moo_ooch_t str_dicputassoc[] = { '_','_','p', 'u', 't', '_', 'a', 's', 's', 'o', 'c', ':' };
static moo_ooch_t str_does_not_understand[] = { 'd', 'o', 'e', 's', 'N', 'o', 't', 'U', 'n', 'd', 'e', 'r', 's', 't', 'a', 'n', 'd', ':' };
static moo_ooch_t str_primitive_failed[] = { 'p', 'r', 'i', 'm', 'i', 't', 'i', 'v', 'e', 'F', 'a', 'i', 'l', 'e', 'd' };
static moo_ooch_t str_unwindto_return[] = { 'u', 'n', 'w', 'i', 'n', 'd', 'T', 'o', ':', 'r', 'e', 't', 'u', 'r', 'n', ':' };
moo_oow_t i; moo_oow_t i;
moo_oop_t sym; moo_oop_t sym;
moo_oop_class_t cls; moo_oop_class_t cls;
@ -603,6 +606,18 @@ static int ignite_3 (moo_t* moo)
if (!sym) return -1; if (!sym) return -1;
moo->dicputassocsym = (moo_oop_char_t)sym; moo->dicputassocsym = (moo_oop_char_t)sym;
sym = moo_makesymbol(moo, str_does_not_understand, MOO_COUNTOF(str_does_not_understand));
if (!sym) return -1;
moo->does_not_understand_sym = (moo_oop_char_t)sym;
sym = moo_makesymbol(moo, str_primitive_failed, MOO_COUNTOF(str_primitive_failed));
if (!sym) return -1;
moo->primitive_failed_sym = (moo_oop_char_t)sym;
sym = moo_makesymbol(moo, str_unwindto_return, MOO_COUNTOF(str_unwindto_return));
if (!sym) return -1;
moo->unwindto_return_sym = (moo_oop_char_t)sym;
return 0; return 0;
} }
@ -937,6 +952,9 @@ void moo_gc (moo_t* moo)
moo->nil_process = (moo_oop_process_t)moo_moveoop(moo, (moo_oop_t)moo->nil_process); moo->nil_process = (moo_oop_process_t)moo_moveoop(moo, (moo_oop_t)moo->nil_process);
moo->dicnewsym = (moo_oop_char_t)moo_moveoop(moo, (moo_oop_t)moo->dicnewsym); moo->dicnewsym = (moo_oop_char_t)moo_moveoop(moo, (moo_oop_t)moo->dicnewsym);
moo->dicputassocsym = (moo_oop_char_t)moo_moveoop(moo, (moo_oop_t)moo->dicputassocsym); moo->dicputassocsym = (moo_oop_char_t)moo_moveoop(moo, (moo_oop_t)moo->dicputassocsym);
moo->does_not_understand_sym = (moo_oop_char_t)moo_moveoop(moo, (moo_oop_t)moo->does_not_understand_sym);
moo->primitive_failed_sym = (moo_oop_char_t)moo_moveoop(moo, (moo_oop_t)moo->primitive_failed_sym);
moo->unwindto_return_sym = (moo_oop_char_t)moo_moveoop(moo, (moo_oop_t)moo->unwindto_return_sym);
for (i = 0; i < moo->sem_list_count; i++) for (i = 0; i < moo->sem_list_count; i++)
{ {

View File

@ -1491,7 +1491,11 @@ struct moo_t
moo_oop_process_t nil_process; /* instance of Process */ moo_oop_process_t nil_process; /* instance of Process */
moo_oop_char_t dicnewsym; /* symbol new: for dictionary */ moo_oop_char_t dicnewsym; /* symbol new: for dictionary */
moo_oop_char_t dicputassocsym; /* symbol put_assoc: for dictionary */ moo_oop_char_t dicputassocsym; /* symbol put_assoc: for dictionary */
moo_oop_char_t does_not_understand_sym; /* symbol doesNotUnderstand: */
moo_oop_char_t primitive_failed_sym; /* symbol primitiveFailed */
moo_oop_char_t unwindto_return_sym; /* symbol unwindTo:return: */
/* pending asynchronous semaphores */ /* pending asynchronous semaphores */
moo_oop_semaphore_t* sem_list; moo_oop_semaphore_t* sem_list;
moo_oow_t sem_list_count; moo_oow_t sem_list_count;

View File

@ -809,7 +809,7 @@ moo_pfrc_t moo_pf_responds_to (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs)
return MOO_PF_FAILURE; return MOO_PF_FAILURE;
} }
if (moo_findmethod(moo, rcv, selector, 0)) if (moo_findmethod(moo, rcv, (moo_oop_char_t)selector, 0))
{ {
MOO_STACK_SETRET (moo, nargs, moo->_true); MOO_STACK_SETRET (moo, nargs, moo->_true);
} }