diff --git a/moo/kernel/Collect.moo b/moo/kernel/Collect.moo index 725172c..09b7d41 100644 --- a/moo/kernel/Collect.moo +++ b/moo/kernel/Collect.moo @@ -314,7 +314,7 @@ class OrderedCollection(SequenceableCollection) method initWithCapacity: capacity { self.buffer := Array new: capacity. - self.firstIndex := capacity div: 2. + self.firstIndex := capacity bitShift: -1. self.lastIndex := self.firstIndex. } @@ -359,7 +359,7 @@ class OrderedCollection(SequenceableCollection) method addFirst: obj { - if (self.firstIndex == 0) { self growBy: 8 shiftBy: 8 }. + if (self.firstIndex == 0) { self __grow_and_shift(8, 8) }. self.firstIndex := self.firstIndex - 1. self.buffer at: self.firstIndex put: obj. ^obj. @@ -367,7 +367,7 @@ class OrderedCollection(SequenceableCollection) method addLast: obj { - if (self.lastIndex == self.buffer size) { self growBy: 8 shiftBy: 0 }. + if (self.lastIndex == self.buffer size) { self __grow_and_shift(8, 0) }. self.buffer at: self.lastIndex put: obj. self.lastIndex := self.lastIndex + 1. ^obj. @@ -377,7 +377,7 @@ class OrderedCollection(SequenceableCollection) { | coll_to_add | coll_to_add := if (self == coll) { coll shallowCopy } else { coll }. - self ensureHeadRoom: (coll_to_add size). + self __ensure_head_room(coll_to_add size). coll_to_add reverseDo: [:obj | self.firstIndex := self.firstIndex - 1. self.buffer at: self.firstIndex put: obj. @@ -389,7 +389,7 @@ class OrderedCollection(SequenceableCollection) { | coll_to_add | coll_to_add := if (self == coll) { coll shallowCopy } else { coll }. - self ensureTailRoom: (coll_to_add size). + self __ensure_tail_room(coll_to_add size). coll_to_add do: [:obj | self.buffer at: self.lastIndex put: obj. self.lastIndex := self.lastIndex + 1. @@ -399,8 +399,14 @@ class OrderedCollection(SequenceableCollection) method add: obj beforeIndex: index { - self insert: obj beforeIndex: index. - ^obj + self __insert_before_index(obj, index). + ^obj. + } + + method add: obj afterIndex: index + { + self __insert_before_index(obj, index + 1). + ^obj. } method removeFirst @@ -462,7 +468,7 @@ class OrderedCollection(SequenceableCollection) ## remove the element at the given position. | obj | obj := self at: index. ## the range is checed by the at: method. - self removeIndex: index + self.firstIndex. + self __remove_Index(index + self.firstIndex). ^obj } @@ -477,7 +483,7 @@ class OrderedCollection(SequenceableCollection) while (i < self.lastIndex) { cand := self.buffer at: i. - if (obj = cand) { self removeIndex: i. ^cand }. + if (obj = cand) { self __remove_index(i). ^cand }. i := i + 1. }. ^error_block value. @@ -525,7 +531,7 @@ class OrderedCollection(SequenceableCollection) ## ------------------------------------------------ ## PRIVATE METHODS ## ------------------------------------------------ - method growBy: grow_size shiftBy: shift_count + method __grow_and_shift(grow_size, shift_count) { | newcon | newcon := (self.buffer class) new: (self.buffer size + grow_size). @@ -537,46 +543,71 @@ class OrderedCollection(SequenceableCollection) self.lastIndex := self.lastIndex + shift_count. } - method ensureHeadRoom: size + method __ensure_head_room(size) { | grow_size | if (self.firstIndex < size) { grow_size := size - self.firstIndex + 8. - self growBy: grow_size shiftBy: grow_size. + self __grow_and_shift(grow_size, grow_size). } } - method ensureTailRoom: size + method __ensure_tail_room(size) { | tmp | tmp := (self.buffer size) - self.lastIndex. ## remaining capacity if (tmp < size) { - tmp := size - tmp + 8. ## grow by this - self growBy: tmp shiftBy: 0. + tmp := size - tmp + 8. ## grow by this amount + self __grow_and_shift(tmp, 0). } } - method insert: obj beforeIndex: index + method __insert_before_index(obj, index) { - ## internal use only - index must be between 0 and self size inclusive + | i start pos cursize reqsize | - | i start | - if (self size == self.buffer size) { self growBy: 8 shiftBy: 8 }. - start := self.firstIndex + index. - i := self.lastIndex. - while (i > start) + if (index <= 0) { - self.buffer at: i put: (self.buffer at: i - 1). - i := i - 1. + ## treat a negative index as the indicator to + ## grow space in the front side. + reqsize := index * -1 + 1. + if (reqsize >= self.firstIndex) { self __ensure_head_room(reqsize) }. + self.firstIndex := self.firstIndex + index - 1. + self.buffer at: self.firstIndex put: obj. + } + else + { + cursize := self size. + if (self.firstIndex > 0 and: [index <= (cursize bitShift: -1)]) + { + start := self.firstIndex - 1. + self.buffer replaceFrom: start to: (start + index - 1) with: self.buffer startingAt: self.firstIndex. + self.buffer at: (start + index) put: obj. + self.firstIndex := start. + } + else + { + reqsize := if (index > cursize) { index - cursize } else { 1 }. + if (reqsize < 8) { reqsize := 8 }. + self __grow_and_shift(reqsize + 8, 0). + + start := self.firstIndex + index. + i := self.lastIndex. + while (i > start) + { + self.buffer at: i put: (self.buffer at: i - 1). + i := i - 1. + }. + pos := index + self.firstIndex. + self.lastIndex := if (pos > self.lastIndex) { pos + 1 } else { self.lastIndex + 1 }. + self.buffer at: pos put: obj. + }. }. - self.lastIndex := self.lastIndex + 1. - self.buffer at: index + self.firstIndex put: obj. - ^obj } - method removeIndex: index + method __remove_index(index) { ## remove an element at the given index from the internal buffer's ## angle. as it is for internal use only, no check is performed diff --git a/moo/lib/comp.c b/moo/lib/comp.c index 89a3b62..a932ddf 100644 --- a/moo/lib/comp.c +++ b/moo/lib/comp.c @@ -105,6 +105,7 @@ static struct voca_t moo_oow_t len; moo_ooch_t str[11]; } vocas[] = { + { 3, { 'a','n','d' } }, { 5, { 'b','r','e','a','k' } }, { 5, { '#','b','y','t','e' } }, { 10, { '#','c','h','a','r','a','c','t','e','r' } }, @@ -137,6 +138,7 @@ static struct voca_t { 3, { 'n','i','l' } }, { 3, { 'o','f','f' } }, { 2, { 'o','n' } }, + { 2, { 'o','r' } }, { 8, { '#','p','o','i','n','t','e','r' } }, { 7, { 'p','o','o','l','d','i','c' } }, { 8, { '#','p','o','o','l','d','i','c' } }, @@ -169,6 +171,7 @@ static struct voca_t enum voca_id_t { + VOCA_AND, VOCA_BREAK, VOCA_BYTE_S, VOCA_CHARACTER_S, @@ -201,6 +204,7 @@ enum voca_id_t VOCA_NIL, VOCA_OFF, VOCA_ON, + VOCA_OR, VOCA_POINTER_S, VOCA_POOLDIC, VOCA_POOLDIC_S, @@ -1228,6 +1232,14 @@ static int get_ident (moo_t* moo, moo_ooci_t char_read_ahead) { SET_TOKEN_TYPE (moo, MOO_IOTOK_CONTINUE); } + else if (is_token_word(moo, VOCA_AND)) + { + SET_TOKEN_TYPE (moo, MOO_IOTOK_AND); + } + else if (is_token_word(moo, VOCA_OR)) + { + SET_TOKEN_TYPE (moo, MOO_IOTOK_OR); + } } return 0; @@ -2621,7 +2633,6 @@ static void eliminate_instructions (moo_t* moo, moo_oow_t start, moo_oow_t end) last = moo->c->mth.code.len - 1; - if (end >= last) { /* eliminate all instructions starting from the start index. @@ -5494,9 +5505,17 @@ static int compile_basic_expression (moo_t* moo, const moo_oocs_t* ident, const /* * basic-expression := expression-primary message-expression? */ + moo_oow_pool_t jumptoend; + moo_oow_pool_chunk_t* jumptoend_chunk; + moo_ioloc_t expr_loc; + moo_oow_t i, j; int to_super; - if (compile_expression_primary(moo, ident, ident_loc, ident_dotted, &to_super) <= -1) return -1; + expr_loc = *TOKEN_LOC(moo); + init_oow_pool (moo, &jumptoend); + +start_over: + if (compile_expression_primary(moo, ident, ident_loc, ident_dotted, &to_super) <= -1) goto oops; #if 0 if (TOKEN_TYPE(moo) != MOO_IOTOK_EOF && @@ -5504,18 +5523,54 @@ static int compile_basic_expression (moo_t* moo, const moo_oocs_t* ident, const TOKEN_TYPE(moo) != MOO_IOTOK_PERIOD && TOKEN_TYPE(moo) != MOO_IOTOK_SEMICOLON) { - if (compile_message_expression(moo, to_super) <= -1) return -1; + if (compile_message_expression(moo, to_super) <= -1) goto oops; } #else if (TOKEN_TYPE(moo) == MOO_IOTOK_IDENT || TOKEN_TYPE(moo) == MOO_IOTOK_BINSEL || TOKEN_TYPE(moo) == MOO_IOTOK_KEYWORD) { - if (compile_message_expression(moo, to_super) <= -1) return -1; + if (compile_message_expression(moo, to_super) <= -1) goto oops; } #endif + + if (TOKEN_TYPE(moo) == MOO_IOTOK_AND) + { + if (add_to_oow_pool(moo, &jumptoend, moo->c->mth.code.len) <= -1 || + emit_single_param_instruction(moo, BCODE_JUMP_FORWARD_IF_FALSE, MAX_CODE_JUMP) <= -1 || + emit_byte_instruction(moo, BCODE_POP_STACKTOP) <= -1) goto oops; + GET_TOKEN (moo); + goto start_over; + } + else if (TOKEN_TYPE(moo) == MOO_IOTOK_OR) + { + if (add_to_oow_pool(moo, &jumptoend, moo->c->mth.code.len) <= -1 || + emit_single_param_instruction(moo, BCODE_JUMP_FORWARD_IF_TRUE, MAX_CODE_JUMP) <= -1 || + emit_byte_instruction(moo, BCODE_POP_STACKTOP) <= -1) goto oops; + GET_TOKEN (moo); + goto start_over; + } + + /* patch instructions that jumps to the end of if expression */ + for (jumptoend_chunk = jumptoend.head, i = 0; jumptoend_chunk; jumptoend_chunk = jumptoend_chunk->next) + { + /* pass expr_loc to every call to patch_long_forward_jump_instruction(). + * it's harmless because if the first call doesn't flood, the subseqent + * call will never flood either. */ + for (j = 0; j < MOO_COUNTOF(jumptoend.static_chunk.buf) && i < jumptoend.count; j++) + { + if (patch_long_forward_jump_instruction (moo, jumptoend_chunk->buf[j], moo->c->mth.code.len, &expr_loc) <= -1) goto oops; + i++; + } + } + + fini_oow_pool (moo, &jumptoend); return 0; + +oops: + fini_oow_pool (moo, &jumptoend); + return -1; } static int compile_braced_block (moo_t* moo) diff --git a/moo/lib/exec.c b/moo/lib/exec.c index 9de8e24..aa299ac 100644 --- a/moo/lib/exec.c +++ b/moo/lib/exec.c @@ -3630,7 +3630,7 @@ static int start_method (moo_t* moo, moo_oop_method_t method, moo_oow_t nargs) #if defined(MOO_DEBUG_VM_EXEC) /* set it to a fake value */ - moo->last_instruction_pointer = 0; + moo->last_inst_pointer = 0; #endif preamble = MOO_OOP_TO_SMOOI(method->preamble); @@ -3765,7 +3765,7 @@ static int start_method (moo_t* moo, moo_oop_method_t method, moo_oow_t nargs) stack_base = moo->sp - nargs - 1; /* stack base before receiver and arguments */ pfnum = MOO_METHOD_GET_PREAMBLE_INDEX(preamble); - LOG_INST1 (moo, "preamble_primitive %zd", pf_no); + LOG_INST1 (moo, "preamble_primitive %zd", pfnum); if (pfnum >= 0 && pfnum < MOO_COUNTOF(pftab)) { diff --git a/moo/lib/moo-prv.h b/moo/lib/moo-prv.h index 765491f..3a0844a 100644 --- a/moo/lib/moo-prv.h +++ b/moo/lib/moo-prv.h @@ -54,7 +54,7 @@ /*#define MOO_DEBUG_LEXER 1*/ #define MOO_DEBUG_COMPILER 1 #define MOO_DEBUG_VM_PROCESSOR 1 -/*#define MOO_DEBUG_VM_EXEC*/ +#define MOO_DEBUG_VM_EXEC #define MOO_PROFILE_VM 1 #endif @@ -353,6 +353,9 @@ enum moo_iotok_type_t MOO_IOTOK_BREAK, MOO_IOTOK_CONTINUE, + MOO_IOTOK_AND, + MOO_IOTOK_OR, + MOO_IOTOK_IDENT, MOO_IOTOK_IDENT_DOTTED, MOO_IOTOK_BINSEL,