From b1c28d03d7c9f83e3291bb9bd0788e9338577efc Mon Sep 17 00:00:00 2001 From: "hyunghwan.chung" Date: Fri, 10 Feb 2017 07:38:29 +0000 Subject: [PATCH] changed VM to emulate 'Dictionary new: ..' for MAKE_DICTIONARY changed VM to emulate 'dic put_assoc: assoc' for POP_INTO_DICTIONARY --- moo/kernel/Collect.moo | 99 +++++++++++++++++++++++++----------------- moo/kernel/Mill.moo | 14 +++--- moo/lib/comp.c | 18 +------- moo/lib/exec.c | 34 ++++++++------- moo/lib/gc.c | 24 +++++++--- moo/lib/moo.h | 2 + 6 files changed, 106 insertions(+), 85 deletions(-) diff --git a/moo/kernel/Collect.moo b/moo/kernel/Collect.moo index 86aec09..e76c76e 100644 --- a/moo/kernel/Collect.moo +++ b/moo/kernel/Collect.moo @@ -130,7 +130,7 @@ class Set(Collection) { dcl tally bucket. - method new: size + method(#class) new: size { ^self new initialize: size. } @@ -211,45 +211,6 @@ class Set(Collection) ^ass } - (* __put_assoc: is a special internal method used by VM to add an association - * to a dictionary with the dictionary/association expression notation. - * :{ :( 1, 20 ), :( #moo, 999) } *) - method __put_assoc: assoc - { - | hv ass bs index ntally key | - - key := assoc key. - bs := self.bucket size. - hv := key hash. - index := hv rem: bs. - - while ((ass := self.bucket at: index) notNil) - { - if (key = ass key) - { - (* found *) - self.bucket at: index put: assoc. - ^self. ## it must return self for the instructions generated by the compiler. - }. - index := (index + 1) rem: bs. - }. - - (* not found *) - ntally := self.tally + 1. - if (ntally >= bs) - { - self.bucket := self __make_expanded_bucket: bs. - bs := self.bucket size. - index := hv rem: bs. - while ((self.bucket at: index) notNil) { index := (index + 1) rem: bs }. - }. - - self.tally := ntally. - self.bucket at: index put: assoc. - - ^self. ## it must return self for the instructions generated by the compiler. - } - method at: key { | ass | @@ -446,6 +407,62 @@ class SymbolSet(Set) class Dictionary(Set) { + (* [NOTE] + * VM require Dictionary to implement new: and __put_assoc + * for the dictionary expression notation - :{ } + *) + + ## TODO: implement Dictionary as a Hashed List/Table or Red-Black Tree + ## Do not inherit Set upon reimplementation + ## + method(#class) new: size + { + ^super new: (size + 10). + } + + (* put_assoc: is called internally by VM to add an association + * to a dictionary with the dictionary/association expression notation + * like this: + * + * :{ :( 1, 20 ), :( #moo, 999) } + * + * it must return self for the way VM works. + *) + method put_assoc: assoc + { + | hv ass bs index ntally key | + + key := assoc key. + bs := self.bucket size. + hv := key hash. + index := hv rem: bs. + + while ((ass := self.bucket at: index) notNil) + { + if (key = ass key) + { + (* found *) + self.bucket at: index put: assoc. + ^self. ## it must return self for the instructions generated by the compiler. + }. + index := (index + 1) rem: bs. + }. + + (* not found *) + ntally := self.tally + 1. + if (ntally >= bs) + { + self.bucket := self __make_expanded_bucket: bs. + bs := self.bucket size. + index := hv rem: bs. + while ((self.bucket at: index) notNil) { index := (index + 1) rem: bs }. + }. + + self.tally := ntally. + self.bucket at: index put: assoc. + + ^self. ## it must return self for the instructions generated by the compiler. + } } pooldic Log @@ -462,7 +479,7 @@ pooldic Log #FATAL := 16. } -class SystemDictionary(Dictionary) +class SystemDictionary(Set) { ## the following methods may not look suitable to be placed ## inside a system dictionary. but they are here for quick and dirty diff --git a/moo/kernel/Mill.moo b/moo/kernel/Mill.moo index 3a5df48..bb49ee2 100644 --- a/moo/kernel/Mill.moo +++ b/moo/kernel/Mill.moo @@ -272,7 +272,7 @@ class MyObject(Object) method(#class) main { - |a| + |a i | a := 100. ## PROBLEM: the following double loop will exhaust the stack @@ -304,19 +304,21 @@ class MyObject(Object) ##:(5, 99), :('ccc', 890) }. - + (*a removeKey: 'bbb'. a remove: :(#bbb).*) - - 1 to: 100 do: [ :i | a at: i put: (i * 2) ]. + + ##1 to: 100 do: [ :i | a at: i put: (i * 2) ]. a keysAndValuesDo: [:k :v | k dump. v dump. '------------' dump. ]. - (a associationAt: :(#aaa)) dump. + (a associationAt: :(#aaa)) dump. + + (* while (true) { while (true) @@ -324,7 +326,7 @@ class MyObject(Object) [:j :q | (j + q) dump] value: (if (true) { 20 }) value: (if (true) { break }). (1 + (if (false) {} else { break })) dump. } - } + }*) } } diff --git a/moo/lib/comp.c b/moo/lib/comp.c index e358d7c..44100de 100644 --- a/moo/lib/comp.c +++ b/moo/lib/comp.c @@ -4177,24 +4177,8 @@ static int compile_dictionary_expression (moo_t* moo) { if (TOKEN_TYPE(moo) == MOO_IOTOK_ASSPAREN) { - moo_oow_t si; - static moo_ooch_t msg[] = { '_', '_','p','u','t','_','a','s','s','o','c',':' }; /* don't put '\0' at the back */ - moo_oocs_t x; - - x.ptr = msg; - x.len = MOO_COUNTOF(msg); - /* [ATTENTION] - * if the method returns self, i don't need DUP_STACKTOP and POP_STACKTOP. - * if the method retruns something else, DUP_STACKTOP and POP_STACKTOP is needed - * to emulate message cascading. - if (emit_byte_instruction (moo, BCODE_DUP_STACKTOP) <= -1 || - compile_association_expression(moo) <= -1 || - add_symbol_literal(moo, &x, 0, &si) <= -1 || - emit_double_param_instruction (moo, BCODE_SEND_MESSAGE_0, 1, si) <= -1 || - emit_byte_instruction (moo, BCODE_POP_STACKTOP) <= -1) return -1; */ if (compile_association_expression(moo) <= -1 || - add_symbol_literal(moo, &x, 0, &si) <= -1 || - emit_double_param_instruction (moo, BCODE_SEND_MESSAGE_0, 1, si) <= -1) return -1; + emit_byte_instruction (moo, BCODE_POP_INTO_DICTIONARY) <= -1) return -1; count++; } else diff --git a/moo/lib/exec.c b/moo/lib/exec.c index 099f208..56ad5ce 100644 --- a/moo/lib/exec.c +++ b/moo/lib/exec.c @@ -3716,7 +3716,7 @@ int moo_execute (moo_t* moo) LOG_INST_3 (moo, "send_message%hs %zu @%zu", (((bcode >> 2) & 1)? "_to_super": ""), b1, b2); if (send_message (moo, selector, ((bcode >> 2) & 1), b1) <= -1) goto oops; - break; /* CMD_SEND_MESSAGE */ + break; } /* -------------------------------------------------------- */ @@ -3795,32 +3795,36 @@ int moo_execute (moo_t* moo) /* -------------------------------------------------------- */ case BCODE_MAKE_DICTIONARY: - { - moo_oop_t t; - FETCH_PARAM_CODE_TO (moo, b1); LOG_INST_1 (moo, "make_dictionary %zu", b1); - /* create an empty array */ - t = (moo_oop_t)moo_makedic (moo, moo->_dictionary, b1 + 10); /* TODO: find a better value than +10 for initial dictionary sizing */ - if (!t) goto oops; - - MOO_STACK_PUSH (moo, t); /* push the array created */ + /* Dictionary new: b1 + * doing this allows users to redefine Dictionary whatever way they like. + * if i did the followings instead, the internal of Dictionary would get + * tied to the system dictionary implementation. the system dictionary + * implementation is flawed in that it accepts only a variable character + * object as a key. it's better to invoke 'Dictionary new: ...'. + t = (moo_oop_t)moo_makedic (moo, moo->_dictionary, b1 + 10); + MOO_STACK_PUSH (moo, t); + */ + MOO_STACK_PUSH (moo, moo->_dictionary); + MOO_STACK_PUSH (moo, MOO_SMOOI_TO_OOP(b1)); + if (send_message (moo, moo->dicnewsym, 0, 1) <= -1) goto oops; break; - } case BCODE_POP_INTO_DICTIONARY: - { - moo_oop_t t1, t2; - LOG_INST_0 (moo, "pop_into_dictionary"); + /* dic __put_assoc: assoc + * whether the system dictinoary implementation is flawed or not, + * the code would look like this if it were used. t1 = MOO_STACK_GETTOP(moo); MOO_STACK_POP (moo); t2 = MOO_STACK_GETTOP(moo); - moo_putatdic (moo, (moo_oop_set_t)t2, ((moo_oop_association_t)t1)->key, ((moo_oop_association_t)t1)->value); /* TODO: 1. erorr check 2. reuse association as it it */ + moo_putatdic (moo, (moo_oop_set_t)t2, ((moo_oop_association_t)t1)->key, ((moo_oop_association_t)t1)->value); + */ + if (send_message (moo, moo->dicputassocsym, 0, 1) <= -1) goto oops; break; - } case BCODE_MAKE_ASSOCIATION: { diff --git a/moo/lib/gc.c b/moo/lib/gc.c index 10214f7..5243e18 100644 --- a/moo/lib/gc.c +++ b/moo/lib/gc.c @@ -279,6 +279,8 @@ static int ignite_3 (moo_t* moo) static moo_ooch_t str_system[] = { 'S','y','s','t','e', 'm' }; 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_dicputassoc[] = { 'p', 'u', 't', '_', 'a', 's', 's', 'o', 'c', ':' }; moo_oow_t i; moo_oop_t sym, cls; @@ -295,16 +297,24 @@ static int ignite_3 (moo_t* moo) moo_ptr++; } - /* Make the system dictionary available as the global name 'Stix' */ - sym = moo_makesymbol (moo, str_system, 6); + /* Make the system dictionary available as the global name 'System' */ + sym = moo_makesymbol (moo, str_system, MOO_COUNTOF(str_system)); if (!sym) return -1; if (!moo_putatsysdic(moo, sym, (moo_oop_t)moo->sysdic)) return -1; /* Make the process scheduler avaialble as the global name 'Processor' */ - sym = moo_makesymbol (moo, str_processor, 9); + sym = moo_makesymbol (moo, str_processor, MOO_COUNTOF(str_processor)); if (!sym) return -1; if (!moo_putatsysdic(moo, sym, (moo_oop_t)moo->processor)) return -1; + sym = moo_makesymbol (moo, str_dicnew, MOO_COUNTOF(str_dicnew)); + if (!sym) return -1; + moo->dicnewsym = sym; + + sym = moo_makesymbol (moo, str_dicputassoc, MOO_COUNTOF(str_dicputassoc)); + if (!sym) return -1; + moo->dicputassocsym = sym; + return 0; } @@ -600,9 +610,11 @@ void moo_gc (moo_t* moo) *(moo_oop_t*)((moo_uint8_t*)moo + kernel_classes[i].offset) = tmp; } - moo->sysdic = (moo_oop_set_t) moo_moveoop (moo, (moo_oop_t)moo->sysdic); - moo->processor = (moo_oop_process_scheduler_t) moo_moveoop (moo, (moo_oop_t)moo->processor); - moo->nil_process = (moo_oop_process_t) moo_moveoop (moo, (moo_oop_t)moo->nil_process); + moo->sysdic = (moo_oop_set_t)moo_moveoop (moo, (moo_oop_t)moo->sysdic); + moo->processor = (moo_oop_process_scheduler_t)moo_moveoop (moo, (moo_oop_t)moo->processor); + 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->dicputassocsym = (moo_oop_char_t)moo_moveoop (moo, (moo_oop_t)moo->dicputassocsym); for (i = 0; i < moo->sem_list_count; i++) { diff --git a/moo/lib/moo.h b/moo/lib/moo.h index bef1617..605cfa5 100644 --- a/moo/lib/moo.h +++ b/moo/lib/moo.h @@ -940,6 +940,8 @@ struct moo_t moo_oop_set_t sysdic; /* system dictionary. instance of SystemDictionary */ moo_oop_process_scheduler_t processor; /* instance of ProcessScheduler */ moo_oop_process_t nil_process; /* instance of Process */ + moo_oop_char_t dicnewsym; /* symbol new: for dictionary */ + moo_oop_char_t dicputassocsym; /* symbol put_assoc: for dictionary */ /* pending asynchronous semaphores */ moo_oop_semaphore_t* sem_list;