diff --git a/moo/kernel/Mill.moo b/moo/kernel/Mill.moo index 9eda1de..5b18f17 100644 --- a/moo/kernel/Mill.moo +++ b/moo/kernel/Mill.moo @@ -192,14 +192,15 @@ class MyObject(Object) a dump. }. a dump. + a := 5. - do { - a := do { - ('in loop.....' & a asString) dump. - ##if (a > 5) { break }. - a := a + 1. - } while(a < 10). - } while (false). + do { + a := do { + ('in loop.....' & a asString) dump. + ##if (a > 5) { break }. + a := a + 1. + } while(a < 10). + } while (false). a dump. ## these should be elimited by the compiler. @@ -213,6 +214,24 @@ class MyObject(Object) nil. ## end of elimination. + a :=999. + a := #{ + 1, + 2, + a, + 4, + 1 + 1, + 2 + 2 + }. + a do: [ :v | v dump]. + +(* + ## how to handle return inside 'if' like the following??? + ## what happens to the stack? + a := if ((k := 20) == 10) {99} else { 100}. + k dump. + a dump. +*) '---------- END ------------' dump. ##Processor sleepFor: 20. } diff --git a/moo/kernel/generr.moo b/moo/kernel/generr.moo index c0d219f..cc936cd 100644 --- a/moo/kernel/generr.moo +++ b/moo/kernel/generr.moo @@ -90,6 +90,7 @@ class MyObject(Object) 'too many block temporaries' 'too many block arguments' 'too large block' + 'too large array expression' 'wrong primitive function number' 'wrong primitive function identifier' 'wrong module name' diff --git a/moo/lib/comp.c b/moo/lib/comp.c index cd37b8a..9531cac 100644 --- a/moo/lib/comp.c +++ b/moo/lib/comp.c @@ -40,6 +40,8 @@ #define NAMESPACE_SIZE 128 /* TODO: choose the right size */ #define POOL_DICTIONARY_SIZE_ALIGN 128 +#define INVALID_IP MOO_TYPE_MAX(moo_oow_t) + enum class_mod_t { CLASS_INDEXED = (1 << 0) @@ -957,7 +959,10 @@ static int get_ident (moo_t* moo, moo_ooci_t char_read_ahead) if (moo->c->in_array && is_leadidentchar(c)) { /* when reading an array literal, read as many characters as - * would compose a normal keyword symbol literal */ + * would compose a normal keyword symbol literal. + * for example, in #(a #b:c: x:y:) x:y: is not preceded + * by #. in an array literal, it should still be treated as + * a symbol. */ do { ADD_TOKEN_CHAR (moo, c); @@ -1564,9 +1569,9 @@ retry: return -1; case '(': - /* #( */ + /* #( - array literal */ ADD_TOKEN_CHAR(moo, c); - SET_TOKEN_TYPE (moo, MOO_IOTOK_ARPAREN); + SET_TOKEN_TYPE (moo, MOO_IOTOK_APAREN); break; case '[': @@ -1575,6 +1580,12 @@ retry: SET_TOKEN_TYPE (moo, MOO_IOTOK_BAPAREN); break; + case '{': + /* #{ - array expression */ + ADD_TOKEN_CHAR(moo, c); + SET_TOKEN_TYPE (moo, MOO_IOTOK_ABRACE); + break; + case '\'': /* quoted symbol literal */ GET_CHAR (moo); @@ -1999,10 +2010,13 @@ static int emit_single_param_instruction (moo_t* moo, int cmd, moo_oow_t param_1 case BCODE_PUSH_INTLIT: case BCODE_PUSH_NEGINTLIT: case BCODE_PUSH_CHARLIT: + case BCODE_MAKE_ARRAY: + case BCODE_POP_INTO_ARRAY: bc = cmd; goto write_long; } + MOO_DEBUG1 (moo, "Invalid single param instruction opcode %d\n", (int)cmd); moo->errnum = MOO_EINVAL; return -1; @@ -2059,6 +2073,7 @@ static int emit_double_param_instruction (moo_t* moo, int cmd, moo_oow_t param_1 goto write_long; } + MOO_DEBUG1 (moo, "Invalid double param instruction opcode %d\n", (int)cmd); moo->errnum = MOO_EINVAL; return -1; @@ -3798,6 +3813,7 @@ static int __read_array_literal (moo_t* moo, moo_oop_t* xlit) lit = moo_makesymbol (moo, TOKEN_NAME_PTR(moo) + 1, TOKEN_NAME_LEN(moo) - 1); break; +/* case MOO_IOTOK_IDENT: case MOO_IOTOK_IDENT_DOTTED: case MOO_IOTOK_BINSEL: @@ -3806,8 +3822,38 @@ static int __read_array_literal (moo_t* moo, moo_oop_t* xlit) case MOO_IOTOK_SUPER: case MOO_IOTOK_THIS_CONTEXT: case MOO_IOTOK_THIS_PROCESS: + case MOO_IOTOK_DO: + case MOO_IOTOK_WHILE: + case MOO_IOTOK_BREAK: + case MOO_IOTOK_CONTINUE: + case MOO_IOTOK_IF: + case MOO_IOTOK_ELSE: + case MOO_IOTOK_ELSIF: lit = moo_makesymbol (moo, TOKEN_NAME_PTR(moo), TOKEN_NAME_LEN(moo)); break; +*/ +/* +a := #(1 2 3 self 5) +a := #(1 2 3 #(1 2 3) self) + +a := #(1, 2, 3, self, 5) <---- is array constant? is array non constant? +if array constant contains a comma, produce MAKE_ARRAY +if array literal contains no comma, it's just a literal array. +what to do with a single element array? no problem if the element is still a literal. +should i allow expression or something like that here??? + +#(( abc )) + +#(1, 2) +* + +make array 10. +push 10 +put array at 1. +push 20 +put array at 2 +if index is too large, switch to at:put? (or don't care as it's too large???). +*/ case MOO_IOTOK_NIL: lit = moo->_nil; @@ -3821,16 +3867,16 @@ static int __read_array_literal (moo_t* moo, moo_oop_t* xlit) lit = moo->_false; break; - case MOO_IOTOK_ERROR: + case MOO_IOTOK_ERROR: /* error */ lit = MOO_ERROR_TO_OOP(MOO_EGENERIC); break; - case MOO_IOTOK_ERRLIT: + case MOO_IOTOK_ERRLIT: /* error(X) */ lit = string_to_error (moo, TOKEN_NAME(moo)); break; - case MOO_IOTOK_ARPAREN: /* #( */ - case MOO_IOTOK_LPAREN: /* ( */ + case MOO_IOTOK_APAREN: /* #( */ + /*case MOO_IOTOK_LPAREN:*/ /* ( */ saved_arlit_count = moo->c->mth.arlit_count; /* TODO: get rid of recursion?? */ GET_TOKEN (moo); @@ -3839,7 +3885,7 @@ static int __read_array_literal (moo_t* moo, moo_oop_t* xlit) break; case MOO_IOTOK_BAPAREN: /* #[ */ - case MOO_IOTOK_LBRACK: /* [ */ + /*case MOO_IOTOK_LBRACK:*/ /* [ */ GET_TOKEN (moo); if (__read_byte_array_literal (moo, &lit) <= -1) return -1; break; @@ -3928,6 +3974,63 @@ static int compile_array_literal (moo_t* moo) return 0; } +static int compile_array_expression (moo_t* moo) +{ + moo_oow_t maip; + moo_ioloc_t aeloc; + + MOO_ASSERT (moo, TOKEN_TYPE(moo) == MOO_IOTOK_ABRACE); + + maip = moo->c->mth.code.len; + if (emit_single_param_instruction(moo, BCODE_MAKE_ARRAY, 0) <= -1) return -1; + + aeloc = *TOKEN_LOC(moo); + GET_TOKEN (moo); /* read a token after #{ */ + if (TOKEN_TYPE(moo) != MOO_IOTOK_RPAREN) + { + moo_oow_t index; + + index = 0; + do + { +/* TODO: check if index exceeds the index that the BCODE_POP_INTO_ARRAY and BCODE_MAKE_ARRAY can support */ + if (compile_method_expression (moo, 0) <= -1) return -1; + if (emit_single_param_instruction (moo, BCODE_POP_INTO_ARRAY, index) <= -1) return -1; + index++; + + if (index > MAX_CODE_PARAM) + { + set_syntax_error (moo, MOO_SYNERR_ARREXPFLOOD, &aeloc, MOO_NULL); + return -1; + } + + if (TOKEN_TYPE(moo) == MOO_IOTOK_RBRACE) break; + + if (TOKEN_TYPE(moo) != MOO_IOTOK_COMMA) + { + set_syntax_error (moo, MOO_SYNERR_COMMA, TOKEN_LOC(moo), TOKEN_NAME(moo)); + return -1; + } + + GET_TOKEN (moo); + } + while (1); + + /* TODO: devise a double_param MAKE_ARRAY to increase the number of elementes supported... */ + /* patch the MAKE_ARRAY instruction */ + #if (MOO_BCODE_LONG_PARAM_SIZE == 2) + moo->c->mth.code.ptr[maip + 1] = index >> 8; + moo->c->mth.code.ptr[maip + 2] = index & 0xFF; + #else + moo->c->mth.code.ptr[maip + 1] = index; + #endif + + } + + GET_TOKEN (moo); /* read a token after } */ + return 0; +} + static int compile_expression_primary (moo_t* moo, const moo_oocs_t* ident, const moo_ioloc_t* ident_loc, int ident_dotted, int* to_super) { /* @@ -4121,12 +4224,14 @@ static int compile_expression_primary (moo_t* moo, const moo_oocs_t* ident, cons if (compile_byte_array_literal(moo) <= -1) return -1; break; - case MOO_IOTOK_ARPAREN: /* #( */ + case MOO_IOTOK_APAREN: /* #( */ /*GET_TOKEN (moo);*/ if (compile_array_literal(moo) <= -1) return -1; break; - /* TODO: dynamic array, non constant array #<> or #{} or what is a better bracket? */ + case MOO_IOTOK_ABRACE: /* #{ */ + if (compile_array_expression(moo) <= -1) return -1; + break; case MOO_IOTOK_LBRACK: /* [ */ { @@ -4520,7 +4625,11 @@ static int compile_conditional (moo_t* moo) } GET_TOKEN (moo); + + /* a weird expression like this is also allowed for the call to compile_method_expression() + * if (if (a == 10) { ^20 }) { ^40 }. */ if (compile_method_expression(moo, 0) <= -1) return -1; + if (TOKEN_TYPE(moo) != MOO_IOTOK_RPAREN) { set_syntax_error (moo, MOO_SYNERR_LPAREN, TOKEN_LOC(moo), TOKEN_NAME(moo)); @@ -4530,8 +4639,6 @@ static int compile_conditional (moo_t* moo) return 0; } -#define INVALID_IP MOO_TYPE_MAX(moo_oow_t) - static int compile_if_expression (moo_t* moo) { moo_oow_pool_t jumptoend; @@ -4876,9 +4983,11 @@ oops: static int compile_method_expression (moo_t* moo, int pop) { /* - * method-expression := method-assignment-expression | basic-expression | if-expression + * method-expression := method-assignment-expression | basic-expression | if-expression | while-expression | do-while-expression * method-assignment-expression := identifier ":=" method-expression * if-expression := if ( ) { } elsif { } else { } + * while-expression := while () {} + * do-while-expression := do { } while () */ moo_oocs_t assignee; @@ -6144,11 +6253,11 @@ static int __compile_pooldic_definition (moo_t* moo) if (!lit) return -1; goto add_literal; - case MOO_IOTOK_BAPAREN: /* #[ - byte array parenthesis */ + case MOO_IOTOK_BAPAREN: /* #[ - byte array literal parenthesis */ if (read_byte_array_literal(moo, &lit) <= -1) return -1; goto add_literal; - case MOO_IOTOK_ARPAREN: /* #( - array parenthesis */ + case MOO_IOTOK_APAREN: /* #( - array literal parenthesis */ if (read_array_literal(moo, &lit) <= -1) return -1; goto add_literal; diff --git a/moo/lib/decode.c b/moo/lib/decode.c index d3d4374..06d96dc 100644 --- a/moo/lib/decode.c +++ b/moo/lib/decode.c @@ -488,6 +488,16 @@ int moo_decode (moo_t* moo, moo_oop_method_t mth, const moo_oocs_t* classfqn) break; /* -------------------------------------------------------- */ + case BCODE_MAKE_ARRAY: + FETCH_PARAM_CODE_TO (moo, b1); + LOG_INST_1 (moo, "make_array %zu", b1); + break; + + case BCODE_POP_INTO_ARRAY: + FETCH_PARAM_CODE_TO (moo, b1); + LOG_INST_1 (moo, "pop_into_array %zu", b1); + break; + case BCODE_DUP_STACKTOP: LOG_INST_0 (moo, "dup_stacktop"); break; diff --git a/moo/lib/err.c b/moo/lib/err.c index 1d6754b..539fe3f 100644 --- a/moo/lib/err.c +++ b/moo/lib/err.c @@ -116,17 +116,18 @@ static moo_ooch_t synerrstr_44[] = {'t','o','o',' ','m','a','n','y',' ','a','r', static moo_ooch_t synerrstr_45[] = {'t','o','o',' ','m','a','n','y',' ','b','l','o','c','k',' ','t','e','m','p','o','r','a','r','i','e','s','\0'}; static moo_ooch_t synerrstr_46[] = {'t','o','o',' ','m','a','n','y',' ','b','l','o','c','k',' ','a','r','g','u','m','e','n','t','s','\0'}; static moo_ooch_t synerrstr_47[] = {'t','o','o',' ','l','a','r','g','e',' ','b','l','o','c','k','\0'}; -static moo_ooch_t synerrstr_48[] = {'w','r','o','n','g',' ','p','r','i','m','i','t','i','v','e',' ','f','u','n','c','t','i','o','n',' ','n','u','m','b','e','r','\0'}; -static moo_ooch_t synerrstr_49[] = {'w','r','o','n','g',' ','p','r','i','m','i','t','i','v','e',' ','f','u','n','c','t','i','o','n',' ','i','d','e','n','t','i','f','i','e','r','\0'}; -static moo_ooch_t synerrstr_50[] = {'w','r','o','n','g',' ','m','o','d','u','l','e',' ','n','a','m','e','\0'}; -static moo_ooch_t synerrstr_51[] = {'#','i','n','c','l','u','d','e',' ','e','r','r','o','r','\0'}; -static moo_ooch_t synerrstr_52[] = {'w','r','o','n','g',' ','n','a','m','e','s','p','a','c','e',' ','n','a','m','e','\0'}; -static moo_ooch_t synerrstr_53[] = {'w','r','o','n','g',' ','p','o','o','l',' ','d','i','c','t','i','o','n','a','r','y',' ','n','a','m','e','\0'}; -static moo_ooch_t synerrstr_54[] = {'d','u','p','l','i','c','a','t','e',' ','p','o','o','l',' ','d','i','c','t','i','o','n','a','r','y',' ','n','a','m','e','\0'}; -static moo_ooch_t synerrstr_55[] = {'l','i','t','e','r','a','l',' ','e','x','p','e','c','t','e','d','\0'}; -static moo_ooch_t synerrstr_56[] = {'b','r','e','a','k',' ','o','r',' ','c','o','n','t','i','n','u','e',' ','n','o','t',' ','w','i','t','h','i','n',' ','a',' ','l','o','o','p','\0'}; -static moo_ooch_t synerrstr_57[] = {'b','r','e','a','k',' ','o','r',' ','c','o','n','t','i','n','u','e',' ','w','i','t','h','i','n',' ','a',' ','b','l','o','c','k','\0'}; -static moo_ooch_t synerrstr_58[] = {'w','h','i','l','e',' ','e','x','p','e','c','t','e','d','\0'}; +static moo_ooch_t synerrstr_48[] = {'t','o','o',' ','l','a','r','g','e',' ','a','r','r','a','y',' ','e','x','p','r','e','s','s','i','o','n','\0'}; +static moo_ooch_t synerrstr_49[] = {'w','r','o','n','g',' ','p','r','i','m','i','t','i','v','e',' ','f','u','n','c','t','i','o','n',' ','n','u','m','b','e','r','\0'}; +static moo_ooch_t synerrstr_50[] = {'w','r','o','n','g',' ','p','r','i','m','i','t','i','v','e',' ','f','u','n','c','t','i','o','n',' ','i','d','e','n','t','i','f','i','e','r','\0'}; +static moo_ooch_t synerrstr_51[] = {'w','r','o','n','g',' ','m','o','d','u','l','e',' ','n','a','m','e','\0'}; +static moo_ooch_t synerrstr_52[] = {'#','i','n','c','l','u','d','e',' ','e','r','r','o','r','\0'}; +static moo_ooch_t synerrstr_53[] = {'w','r','o','n','g',' ','n','a','m','e','s','p','a','c','e',' ','n','a','m','e','\0'}; +static moo_ooch_t synerrstr_54[] = {'w','r','o','n','g',' ','p','o','o','l',' ','d','i','c','t','i','o','n','a','r','y',' ','n','a','m','e','\0'}; +static moo_ooch_t synerrstr_55[] = {'d','u','p','l','i','c','a','t','e',' ','p','o','o','l',' ','d','i','c','t','i','o','n','a','r','y',' ','n','a','m','e','\0'}; +static moo_ooch_t synerrstr_56[] = {'l','i','t','e','r','a','l',' ','e','x','p','e','c','t','e','d','\0'}; +static moo_ooch_t synerrstr_57[] = {'b','r','e','a','k',' ','o','r',' ','c','o','n','t','i','n','u','e',' ','n','o','t',' ','w','i','t','h','i','n',' ','a',' ','l','o','o','p','\0'}; +static moo_ooch_t synerrstr_58[] = {'b','r','e','a','k',' ','o','r',' ','c','o','n','t','i','n','u','e',' ','w','i','t','h','i','n',' ','a',' ','b','l','o','c','k','\0'}; +static moo_ooch_t synerrstr_59[] = {'w','h','i','l','e',' ','e','x','p','e','c','t','e','d','\0'}; static moo_ooch_t* synerrstr[] = { synerrstr_0, synerrstr_1, synerrstr_2, synerrstr_3, synerrstr_4, synerrstr_5, synerrstr_6, synerrstr_7, @@ -136,7 +137,7 @@ static moo_ooch_t* synerrstr[] = synerrstr_32, synerrstr_33, synerrstr_34, synerrstr_35, synerrstr_36, synerrstr_37, synerrstr_38, synerrstr_39, synerrstr_40, synerrstr_41, synerrstr_42, synerrstr_43, synerrstr_44, synerrstr_45, synerrstr_46, synerrstr_47, synerrstr_48, synerrstr_49, synerrstr_50, synerrstr_51, synerrstr_52, synerrstr_53, synerrstr_54, synerrstr_55, - synerrstr_56, synerrstr_57, synerrstr_58 + synerrstr_56, synerrstr_57, synerrstr_58, synerrstr_59 }; #endif /* END: GENERATED WITH generr.st */ diff --git a/moo/lib/exec.c b/moo/lib/exec.c index 6ad36e6..6d61c36 100644 --- a/moo/lib/exec.c +++ b/moo/lib/exec.c @@ -3795,6 +3795,35 @@ int moo_execute (moo_t* moo) break; /* -------------------------------------------------------- */ + case BCODE_MAKE_ARRAY: + { + moo_oop_t t; + + FETCH_PARAM_CODE_TO (moo, b1); + LOG_INST_1 (moo, "make_array %zu", b1); + + /* create an empty array */ + t = moo_instantiate (moo, moo->_array, MOO_NULL, b1); + if (!t) goto oops; + + MOO_STACK_PUSH (moo, t); /* push the array created */ + break; + } + + case BCODE_POP_INTO_ARRAY: + { + moo_oop_t t1, t2; + + FETCH_PARAM_CODE_TO (moo, b1); + LOG_INST_1 (moo, "pop_into_array %zu", b1); + + t1 = MOO_STACK_GETTOP(moo); + MOO_STACK_POP (moo); + t2 = MOO_STACK_GETTOP(moo); + ((moo_oop_oop_t)t2)->slot[b1] = t1; + break; + } + case BCODE_DUP_STACKTOP: { moo_oop_t t; @@ -3951,7 +3980,7 @@ int moo_execute (moo_t* moo) MOO_LOG0 (moo, MOO_LOG_IC | MOO_LOG_ERROR, "Error - cannot return from dead context\n"); moo->errnum = MOO_EINTERN; /* TODO: can i make this error catchable at the moo level? */ - return -1; + goto oops; non_local_return_ok: /*MOO_DEBUG2 (moo, "NON_LOCAL RETURN OK TO... %p %p\n", moo->active_context->origin, moo->active_context->origin->sender);*/ @@ -3988,7 +4017,7 @@ int moo_execute (moo_t* moo) MOO_STACK_PUSH (moo, (moo_oop_t)unwind_stop); MOO_STACK_PUSH (moo, (moo_oop_t)return_value); - if (send_private_message (moo, fbm, 16, 0, 2) <= -1) return -1; + if (send_private_message (moo, fbm, 16, 0, 2) <= -1) goto oops; } else { @@ -4081,7 +4110,7 @@ int moo_execute (moo_t* moo) * this base block context is created with no stack for * this reason */ blkctx = (moo_oop_context_t)moo_instantiate (moo, moo->_block_context, MOO_NULL, 0); - if (!blkctx) return -1; + if (!blkctx) goto oops; /* the long forward jump instruction has the format of * 11000100 KKKKKKKK or 11000100 KKKKKKKK KKKKKKKK @@ -4138,7 +4167,7 @@ int moo_execute (moo_t* moo) * this base block context is created with no * stack for this reason. */ blkctx = (moo_oop_context_t)moo_instantiate (moo, moo->_block_context, MOO_NULL, 0); - if (!blkctx) return -1; + if (!blkctx) goto oops; /* get the receiver to the block copy message after block context instantiation * not to get affected by potential GC */ diff --git a/moo/lib/main.c b/moo/lib/main.c index 873a8f3..400a72d 100644 --- a/moo/lib/main.c +++ b/moo/lib/main.c @@ -159,7 +159,6 @@ static MOO_INLINE moo_ooi_t open_input (moo_t* moo, moo_ioarg_t* arg) xtn_t* xtn = moo_getxtn(moo); bb_t* bb = MOO_NULL; - /* TOOD: support predefined include directory as well */ if (arg->includer) { diff --git a/moo/lib/moo-prv.h b/moo/lib/moo-prv.h index 7a19cbc..e567fa9 100644 --- a/moo/lib/moo-prv.h +++ b/moo/lib/moo-prv.h @@ -323,8 +323,9 @@ struct moo_iotok_t MOO_IOTOK_RBRACK, MOO_IOTOK_LPAREN, MOO_IOTOK_RPAREN, - MOO_IOTOK_ARPAREN, /* #( */ + MOO_IOTOK_APAREN, /* #( */ MOO_IOTOK_BAPAREN, /* #[ */ + MOO_IOTOK_ABRACE, /* #{ */ MOO_IOTOK_PERIOD, MOO_IOTOK_COMMA, MOO_IOTOK_SEMICOLON, @@ -862,6 +863,8 @@ enum moo_bcode_t /* -------------------------------------- */ + BCODE_MAKE_ARRAY = 0xF5, /* 245 */ + BCODE_POP_INTO_ARRAY = 0xF6, /* 246 */ BCODE_DUP_STACKTOP = 0xF7, BCODE_POP_STACKTOP = 0xF8, BCODE_RETURN_STACKTOP = 0xF9, /* ^something */ diff --git a/moo/lib/moo.h b/moo/lib/moo.h index 8eab078..021f7af 100644 --- a/moo/lib/moo.h +++ b/moo/lib/moo.h @@ -1139,6 +1139,7 @@ enum moo_synerrnum_t MOO_SYNERR_BLKTMPRFLOOD, /* too many block temporaries */ MOO_SYNERR_BLKARGFLOOD, /* too many block arguments */ MOO_SYNERR_BLKFLOOD, /* too large block */ + MOO_SYNERR_ARREXPFLOOD, /* too large array expression */ MOO_SYNERR_PFNUM, /* wrong primitive number */ MOO_SYNERR_PFID, /* wrong primitive identifier */ MOO_SYNERR_MODNAME, /* wrong module name */