changed VM to emulate 'Dictionary new: ..' for MAKE_DICTIONARY
changed VM to emulate 'dic put_assoc: assoc' for POP_INTO_DICTIONARY
This commit is contained in:
parent
46f3e8635e
commit
b1c28d03d7
@ -130,7 +130,7 @@ class Set(Collection)
|
|||||||
{
|
{
|
||||||
dcl tally bucket.
|
dcl tally bucket.
|
||||||
|
|
||||||
method new: size
|
method(#class) new: size
|
||||||
{
|
{
|
||||||
^self new initialize: size.
|
^self new initialize: size.
|
||||||
}
|
}
|
||||||
@ -211,45 +211,6 @@ class Set(Collection)
|
|||||||
^ass
|
^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
|
method at: key
|
||||||
{
|
{
|
||||||
| ass |
|
| ass |
|
||||||
@ -446,6 +407,62 @@ class SymbolSet(Set)
|
|||||||
|
|
||||||
class Dictionary(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
|
pooldic Log
|
||||||
@ -462,7 +479,7 @@ pooldic Log
|
|||||||
#FATAL := 16.
|
#FATAL := 16.
|
||||||
}
|
}
|
||||||
|
|
||||||
class SystemDictionary(Dictionary)
|
class SystemDictionary(Set)
|
||||||
{
|
{
|
||||||
## the following methods may not look suitable to be placed
|
## the following methods may not look suitable to be placed
|
||||||
## inside a system dictionary. but they are here for quick and dirty
|
## inside a system dictionary. but they are here for quick and dirty
|
||||||
|
@ -272,7 +272,7 @@ class MyObject(Object)
|
|||||||
|
|
||||||
method(#class) main
|
method(#class) main
|
||||||
{
|
{
|
||||||
|a|
|
|a i |
|
||||||
|
|
||||||
a := 100.
|
a := 100.
|
||||||
## PROBLEM: the following double loop will exhaust the stack
|
## PROBLEM: the following double loop will exhaust the stack
|
||||||
@ -308,15 +308,17 @@ class MyObject(Object)
|
|||||||
(*a removeKey: 'bbb'.
|
(*a removeKey: 'bbb'.
|
||||||
a remove: :(#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 |
|
a keysAndValuesDo: [:k :v |
|
||||||
k dump.
|
k dump.
|
||||||
v dump.
|
v dump.
|
||||||
'------------' dump.
|
'------------' dump.
|
||||||
].
|
].
|
||||||
|
|
||||||
|
|
||||||
(a associationAt: :(#aaa)) dump.
|
(a associationAt: :(#aaa)) dump.
|
||||||
|
|
||||||
|
(*
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
while (true)
|
while (true)
|
||||||
@ -324,7 +326,7 @@ class MyObject(Object)
|
|||||||
[:j :q | (j + q) dump] value: (if (true) { 20 }) value: (if (true) { break }).
|
[:j :q | (j + q) dump] value: (if (true) { 20 }) value: (if (true) { break }).
|
||||||
(1 + (if (false) {} else { break })) dump.
|
(1 + (if (false) {} else { break })) dump.
|
||||||
}
|
}
|
||||||
}
|
}*)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4177,24 +4177,8 @@ static int compile_dictionary_expression (moo_t* moo)
|
|||||||
{
|
{
|
||||||
if (TOKEN_TYPE(moo) == MOO_IOTOK_ASSPAREN)
|
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 ||
|
if (compile_association_expression(moo) <= -1 ||
|
||||||
add_symbol_literal(moo, &x, 0, &si) <= -1 ||
|
emit_byte_instruction (moo, BCODE_POP_INTO_DICTIONARY) <= -1) return -1;
|
||||||
emit_double_param_instruction (moo, BCODE_SEND_MESSAGE_0, 1, si) <= -1) return -1;
|
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -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);
|
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;
|
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:
|
case BCODE_MAKE_DICTIONARY:
|
||||||
{
|
|
||||||
moo_oop_t t;
|
|
||||||
|
|
||||||
FETCH_PARAM_CODE_TO (moo, b1);
|
FETCH_PARAM_CODE_TO (moo, b1);
|
||||||
LOG_INST_1 (moo, "make_dictionary %zu", b1);
|
LOG_INST_1 (moo, "make_dictionary %zu", b1);
|
||||||
|
|
||||||
/* create an empty array */
|
/* Dictionary new: b1
|
||||||
t = (moo_oop_t)moo_makedic (moo, moo->_dictionary, b1 + 10); /* TODO: find a better value than +10 for initial dictionary sizing */
|
* doing this allows users to redefine Dictionary whatever way they like.
|
||||||
if (!t) goto oops;
|
* if i did the followings instead, the internal of Dictionary would get
|
||||||
|
* tied to the system dictionary implementation. the system dictionary
|
||||||
MOO_STACK_PUSH (moo, t); /* push the array created */
|
* 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;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
case BCODE_POP_INTO_DICTIONARY:
|
case BCODE_POP_INTO_DICTIONARY:
|
||||||
{
|
|
||||||
moo_oop_t t1, t2;
|
|
||||||
|
|
||||||
LOG_INST_0 (moo, "pop_into_dictionary");
|
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);
|
t1 = MOO_STACK_GETTOP(moo);
|
||||||
MOO_STACK_POP (moo);
|
MOO_STACK_POP (moo);
|
||||||
t2 = MOO_STACK_GETTOP(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;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
case BCODE_MAKE_ASSOCIATION:
|
case BCODE_MAKE_ASSOCIATION:
|
||||||
{
|
{
|
||||||
|
24
moo/lib/gc.c
24
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_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_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_oow_t i;
|
||||||
moo_oop_t sym, cls;
|
moo_oop_t sym, cls;
|
||||||
@ -295,16 +297,24 @@ static int ignite_3 (moo_t* moo)
|
|||||||
moo_ptr++;
|
moo_ptr++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make the system dictionary available as the global name 'Stix' */
|
/* Make the system dictionary available as the global name 'System' */
|
||||||
sym = moo_makesymbol (moo, str_system, 6);
|
sym = moo_makesymbol (moo, str_system, MOO_COUNTOF(str_system));
|
||||||
if (!sym) return -1;
|
if (!sym) return -1;
|
||||||
if (!moo_putatsysdic(moo, sym, (moo_oop_t)moo->sysdic)) return -1;
|
if (!moo_putatsysdic(moo, sym, (moo_oop_t)moo->sysdic)) return -1;
|
||||||
|
|
||||||
/* Make the process scheduler avaialble as the global name 'Processor' */
|
/* 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 (!sym) return -1;
|
||||||
if (!moo_putatsysdic(moo, sym, (moo_oop_t)moo->processor)) 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;
|
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_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->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->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->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++)
|
for (i = 0; i < moo->sem_list_count; i++)
|
||||||
{
|
{
|
||||||
|
@ -940,6 +940,8 @@ struct moo_t
|
|||||||
moo_oop_set_t sysdic; /* system dictionary. instance of SystemDictionary */
|
moo_oop_set_t sysdic; /* system dictionary. instance of SystemDictionary */
|
||||||
moo_oop_process_scheduler_t processor; /* instance of ProcessScheduler */
|
moo_oop_process_scheduler_t processor; /* instance of ProcessScheduler */
|
||||||
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 dicputassocsym; /* symbol put_assoc: for dictionary */
|
||||||
|
|
||||||
/* pending asynchronous semaphores */
|
/* pending asynchronous semaphores */
|
||||||
moo_oop_semaphore_t* sem_list;
|
moo_oop_semaphore_t* sem_list;
|
||||||
|
Loading…
Reference in New Issue
Block a user