diff --git a/moo/lib/comp.c b/moo/lib/comp.c index 749d739..5806446 100644 --- a/moo/lib/comp.c +++ b/moo/lib/comp.c @@ -99,6 +99,7 @@ static struct voca_t { 8, { '#','i','n','c','l','u','d','e' } }, { 7, { '#','l','i','w','o','r','d' } }, { 6, { 'm','e','t','h','o','d' } }, + { 7, { '#','n','a','t','i','v','e' } }, { 3, { 'n','i','l' } }, { 8, { '#','p','o','i','n','t','e','r' } }, { 7, { 'p','o','o','l','d','i','c' } }, @@ -144,6 +145,7 @@ enum voca_id_t VOCA_INCLUDE_S, VOCA_LIWORD_S, VOCA_METHOD, + VOCA_NATIVE_S, VOCA_NIL, VOCA_POINTER_S, VOCA_POOLDIC, @@ -5773,6 +5775,7 @@ static int compile_method_definition (moo_t* moo) { /* clear data required to compile a method */ moo->c->mth.type = MOO_METHOD_INSTANCE; + moo->c->mth.native = 0; moo->c->mth.text.len = 0; moo->c->mth.assignees.len = 0; moo->c->mth.binsels.len = 0; @@ -5794,6 +5797,7 @@ static int compile_method_definition (moo_t* moo) if (TOKEN_TYPE(moo) == MOO_IOTOK_LPAREN) { /* process method modifiers */ + next_modifier: GET_TOKEN (moo); if (is_token_symbol(moo, VOCA_CLASS_S)) @@ -5802,6 +5806,17 @@ static int compile_method_definition (moo_t* moo) moo->c->mth.type = MOO_METHOD_CLASS; GET_TOKEN (moo); } + else if (is_token_symbol(moo, VOCA_NATIVE_S)) + { + /* method(#native) */ + moo->c->mth.native = 1; + GET_TOKEN (moo); + } + + if (TOKEN_TYPE(moo) == MOO_IOTOK_COMMA) + { + goto next_modifier; + } if (TOKEN_TYPE(moo) != MOO_IOTOK_RPAREN) { @@ -5815,27 +5830,40 @@ static int compile_method_definition (moo_t* moo) if (compile_method_name(moo) <= -1) return -1; - if (TOKEN_TYPE(moo) != MOO_IOTOK_LBRACE) + if (moo->c->mth.native) { - /* { expected */ - set_syntax_error (moo, MOO_SYNERR_LBRACE, TOKEN_LOC(moo), TOKEN_NAME(moo)); - return -1; + if (TOKEN_TYPE(moo) != MOO_IOTOK_PERIOD) + { + /* . expected */ + set_syntax_error (moo, MOO_SYNERR_PERIOD, TOKEN_LOC(moo), TOKEN_NAME(moo)); + return -1; + } + } + else + { + if (TOKEN_TYPE(moo) != MOO_IOTOK_LBRACE) + { + /* { expected */ + set_syntax_error (moo, MOO_SYNERR_LBRACE, TOKEN_LOC(moo), TOKEN_NAME(moo)); + return -1; + } + + GET_TOKEN (moo); + + if (compile_method_temporaries(moo) <= -1 || + compile_method_primitive(moo) <= -1 || + compile_method_statements(moo) <= -1) return -1; + + if (TOKEN_TYPE(moo) != MOO_IOTOK_RBRACE) + { + /* } expected */ + set_syntax_error (moo, MOO_SYNERR_RBRACE, TOKEN_LOC(moo), TOKEN_NAME(moo)); + return -1; + } } GET_TOKEN (moo); - if (compile_method_temporaries(moo) <= -1 || - compile_method_primitive(moo) <= -1 || - compile_method_statements(moo) <= -1) return -1; - - if (TOKEN_TYPE(moo) != MOO_IOTOK_RBRACE) - { - /* } expected */ - set_syntax_error (moo, MOO_SYNERR_RBRACE, TOKEN_LOC(moo), TOKEN_NAME(moo)); - return -1; - } - GET_TOKEN (moo); - /* add a compiled method to the method dictionary */ if (add_compiled_method(moo) <= -1) return -1; diff --git a/moo/lib/exec.c b/moo/lib/exec.c index ecce7ea..93a732d 100644 --- a/moo/lib/exec.c +++ b/moo/lib/exec.c @@ -557,6 +557,8 @@ static moo_oop_process_t signal_semaphore (moo_t* moo, moo_oop_semaphore_t sem) unchain_from_semaphore (moo, proc); resume_process (moo, proc); /* TODO: error check */ + if (MOO_OOP_TO_SMOOI(sem->io_index) >= 0) moo->sem_io_wait_count--; + /* return the resumed(runnable) process */ return proc; } @@ -587,6 +589,8 @@ static void await_semaphore (moo_t* moo, moo_oop_semaphore_t sem) MOO_ASSERT (moo, sem->waiting_tail == proc); + if (MOO_OOP_TO_SMOOI(sem->io_index) >= 0) moo->sem_io_wait_count++; + MOO_ASSERT (moo, moo->processor->active != proc); } } @@ -789,7 +793,6 @@ MOO_DEBUG1 (moo, "ADDED TO SEM IO => sem_io_count => %d\n", (int)moo->sem_io_cou static void delete_from_sem_io (moo_t* moo, moo_ooi_t index) { - moo_oop_semaphore_t sem, lastsem; sem = moo->sem_io[index]; @@ -835,6 +838,7 @@ static void signal_io_semaphore (moo_t* moo, int mask, void* ctx) wake_new_process (moo, proc); /* switch to running */ moo->proc_switched = 1; } + } else { @@ -2172,17 +2176,17 @@ static moo_pfrc_t __processor_add_io_semaphore (moo_t* moo, moo_ooi_t nargs, int static moo_pfrc_t pf_processor_add_input_semaphore (moo_t* moo, moo_ooi_t nargs) { - return __processor_add_io_semaphore (moo, nargs, 1); + return __processor_add_io_semaphore (moo, nargs, MOO_SEMAPHORE_IO_MASK_INPUT); } static moo_pfrc_t pf_processor_add_output_semaphore (moo_t* moo, moo_ooi_t nargs) { - return __processor_add_io_semaphore (moo, nargs, 2); + return __processor_add_io_semaphore (moo, nargs, MOO_SEMAPHORE_IO_MASK_OUTPUT); } static moo_pfrc_t pf_processor_add_inoutput_semaphore (moo_t* moo, moo_ooi_t nargs) { - return __processor_add_io_semaphore (moo, nargs, 3); + return __processor_add_io_semaphore (moo, nargs, MOO_SEMAPHORE_IO_MASK_INPUT | MOO_SEMAPHORE_IO_MASK_OUTPUT); } static moo_pfrc_t pf_processor_remove_semaphore (moo_t* moo, moo_ooi_t nargs) @@ -3156,7 +3160,7 @@ static MOO_INLINE int switch_process_if_needed (moo_t* moo) /* no running process */ MOO_SUBNTIME (&ft, &ft, (moo_ntime_t*)&now); - if (moo->sem_io_count > 0) + if (moo->sem_io_wait_count > 0) { MOO_DEBUG0 (moo, "ABOUT TO CALL VM_MUX_WAIT()\n"); vm_mux_wait (moo, &ft); @@ -3177,7 +3181,11 @@ MOO_DEBUG0 (moo, "ABOUT TO CALL VM_MUX_SLEEP()\n"); while (moo->sem_heap_count > 0 && !moo->abort_req); } - if (moo->sem_io_count > 0) vm_mux_wait (moo, MOO_NULL); + if (moo->sem_io_wait_count > 0) + { +MOO_DEBUG0 (moo, "ABOUT TO CALL VM_MUX_WAIT 222()\n"); + vm_mux_wait (moo, MOO_NULL); + } if (moo->processor->active == moo->nil_process) { @@ -3239,6 +3247,13 @@ int moo_execute (moo_t* moo) MOO_ASSERT (moo, moo->active_context != MOO_NULL); +/* TODO: initialize semaphore stuffs + * sem_heap + * sem_io. + * sem_list. + * these can be dirty if this function is called again esepcially after failure. + */ + if (vm_startup(moo) <= -1) goto oops; vm_startup_called = 1; diff --git a/moo/lib/main.c b/moo/lib/main.c index a2e96cc..e2be2a5 100644 --- a/moo/lib/main.c +++ b/moo/lib/main.c @@ -832,9 +832,10 @@ static int mux_add (moo_t* moo, moo_oop_semaphore_t sem) MOO_ASSERT (moo, MOO_OOP_IS_SMOOI(sem->io_mask)); mask = MOO_OOP_TO_SMOOI(sem->io_mask); - ev.events = 0; - if (mask & 1) ev.events |= EPOLLIN; /*TODO: define io mask constants... */ - if (mask & 2) ev.events |= EPOLLOUT; + ev.events = EPOLLET; /* edge trigger */ + if (mask & MOO_SEMAPHORE_IO_MASK_INPUT) ev.events |= EPOLLIN; /*TODO: define io mask constants... */ + if (mask & MOO_SEMAPHORE_IO_MASK_OUTPUT) ev.events |= EPOLLOUT; + /* don't check MOO_SEMAPHORE_IO_MASK_ERROR and MOO_SEMAPHORE_IO_MASK_HANGUP as it's implicitly enabled by epoll() */ ev.data.ptr = (void*)MOO_OOP_TO_SMOOI(sem->io_index); if (ev.events == 0) @@ -882,10 +883,10 @@ static void mux_wait (moo_t* moo, const moo_ntime_t* dur, moo_vmprim_muxwait_cb_ --n; mask = 0; - if (ev[n].events & EPOLLIN) mask |= 1; /* TODO define constants for IO Mask */ - if (ev[n].events & EPOLLOUT) mask |= 2; - if (ev[n].events & EPOLLERR) mask |= 4; - if (ev[n].events & EPOLLHUP) mask |= 8; + if (ev[n].events & EPOLLIN) mask |= MOO_SEMAPHORE_IO_MASK_INPUT; /* TODO define constants for IO Mask */ + if (ev[n].events & EPOLLOUT) mask |= MOO_SEMAPHORE_IO_MASK_OUTPUT; + if (ev[n].events & EPOLLERR) mask |= MOO_SEMAPHORE_IO_MASK_ERROR; + if (ev[n].events & EPOLLHUP) mask |= MOO_SEMAPHORE_IO_MASK_HANGUP; muxwcb (moo, mask, ev[n].data.ptr); } diff --git a/moo/lib/moo-prv.h b/moo/lib/moo-prv.h index 5ccb166..dc83324 100644 --- a/moo/lib/moo-prv.h +++ b/moo/lib/moo-prv.h @@ -475,6 +475,7 @@ struct moo_compiler_t struct { moo_method_type_t type; + int native; /* method source text */ moo_oocs_t text; diff --git a/moo/lib/moo.c b/moo/lib/moo.c index 2778ba4..6ad72cf 100644 --- a/moo/lib/moo.c +++ b/moo/lib/moo.c @@ -162,6 +162,7 @@ void moo_fini (moo_t* moo) moo_freemem (moo, moo->sem_io); moo->sem_io_capa = 0; moo->sem_io_count = 0; + moo->sem_io_wait_count = 0; } for (cb = moo->cblist; cb; cb = cb->next) @@ -173,6 +174,7 @@ void moo_fini (moo_t* moo) moo_rbt_fini (&moo->modtab); /* TOOD: persistency? storing objects to image file? */ + moo_killheap (moo, moo->newheap); moo_killheap (moo, moo->curheap); moo_killheap (moo, moo->permheap); diff --git a/moo/lib/moo.h b/moo/lib/moo.h index 458cd51..bca6afa 100644 --- a/moo/lib/moo.h +++ b/moo/lib/moo.h @@ -684,6 +684,11 @@ struct moo_process_t moo_oop_t slot[1]; /* process stack */ }; +#define MOO_SEMAPHORE_IO_MASK_INPUT 1 +#define MOO_SEMAPHORE_IO_MASK_OUTPUT 2 +#define MOO_SEMAPHORE_IO_MASK_HANGUP 4 +#define MOO_SEMAPHORE_IO_MASK_ERROR 8 + struct moo_semaphore_t { MOO_OBJ_HEADER; @@ -1004,6 +1009,7 @@ struct moo_t moo_oop_semaphore_t* sem_io; moo_oow_t sem_io_count; moo_oow_t sem_io_capa; + moo_oow_t sem_io_wait_count; moo_oop_t* tmp_stack[256]; /* stack for temporaries */ moo_oow_t tmp_count; diff --git a/moo/mod/x11.c b/moo/mod/x11.c index a37c8ea..f4ab680 100644 --- a/moo/mod/x11.c +++ b/moo/mod/x11.c @@ -28,9 +28,8 @@ #include #include -#include - #include +#include #define C MOO_METHOD_CLASS #define I MOO_METHOD_INSTANCE @@ -40,12 +39,15 @@ typedef struct x11_t x11_t; struct x11_t { xcb_connection_t* c; + xcb_window_t w; + xcb_intern_atom_reply_t* dwcr; /* TODO: move this to each window */ }; typedef struct x11_win_t x11_win_t; struct x11_win_t { xcb_window_t w; + }; /* ------------------------------------------------------------------------ */ @@ -63,6 +65,13 @@ static moo_pfrc_t pf_connect (moo_t* moo, moo_ooi_t nargs) } x11 = (x11_t*)moo_getobjtrailer(moo, MOO_STACK_GETRCV(moo, nargs), MOO_NULL); + + if (x11->c) + { + MOO_DEBUG0 (moo, " Unable to connect multiple times\n"); + goto softfail; + } + /* name = MOO_STACK_GETARG(moo, nargs, 0); @@ -98,8 +107,11 @@ static moo_pfrc_t pf_disconnect (moo_t* moo, moo_ooi_t nargs) MOO_DEBUG1 (moo, " %p\n", x11->c); - xcb_disconnect (x11->c); - x11->c = MOO_NULL; + if (x11->c) + { + xcb_disconnect (x11->c); + x11->c = MOO_NULL; + } MOO_STACK_SETRETTORCV (moo, nargs); return MOO_PF_SUCCESS; @@ -145,12 +157,28 @@ static moo_pfrc_t pf_getevent (moo_t* moo, moo_ooi_t nargs) evt = xcb_poll_for_event(x11->c); if (evt) { - MOO_STACK_SETRET (moo, nargs, MOO_SMOOI_TO_OOP(evt->response_type)); /* TODO: translate evt to the event object */ + uint8_t evttype = evt->response_type & ~0x80; + + if (evttype == XCB_CLIENT_MESSAGE && + ((xcb_client_message_event_t*)evt)->data.data32[0] == x11->dwcr->atom) + { + xcb_unmap_window (x11->c, x11->w); + xcb_destroy_window (x11->c, x11->w); + xcb_flush (x11->c); + MOO_STACK_SETRET (moo, nargs, MOO_SMOOI_TO_OOP(9999)); /* TODO: translate evt to the event object */ + } + else + { + MOO_STACK_SETRET (moo, nargs, MOO_SMOOI_TO_OOP(evttype)); /* TODO: translate evt to the event object */ + } + free (evt); } else { +MOO_DEBUG0(moo, "BBBBBBBBBBBBbb GOT NO EVENT...\n"); MOO_STACK_SETRET (moo, nargs, moo->_nil); } + return MOO_PF_SUCCESS; } @@ -158,28 +186,49 @@ static moo_pfrc_t pf_makewin (moo_t* moo, moo_ooi_t nargs) { x11_t* x11; xcb_screen_t* screen; - xcb_window_t win; + uint32_t mask; + uint32_t values[2]; + xcb_intern_atom_cookie_t cookie; + xcb_intern_atom_reply_t* reply; x11 = (x11_t*)moo_getobjtrailer(moo, MOO_STACK_GETRCV(moo, nargs), MOO_NULL); MOO_DEBUG1 (moo, " %p\n", x11->c); screen = xcb_setup_roots_iterator(xcb_get_setup(x11->c)).data; - win = xcb_generate_id (x11->c); + x11->w = xcb_generate_id (x11->c); - xcb_create_window (x11->c, + mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK; + values[0] = screen->white_pixel; + values[1] = XCB_EVENT_MASK_KEY_RELEASE | + XCB_EVENT_MASK_BUTTON_PRESS | + XCB_EVENT_MASK_EXPOSURE | + /*XCB_EVENT_MASK_POINTER_MOTION |*/ + XCB_EVENT_MASK_ENTER_WINDOW | + XCB_EVENT_MASK_LEAVE_WINDOW | + XCB_EVENT_MASK_VISIBILITY_CHANGE; + xcb_create_window ( + x11->c, XCB_COPY_FROM_PARENT, - win, + x11->w, screen->root, 0, 0, 300, 300, 10, XCB_WINDOW_CLASS_INPUT_OUTPUT, screen->root_visual, - 0, MOO_NULL); + mask, values); -/*TODO: use xcb_request_check() for error handling */ - xcb_map_window (x11->c, win); + cookie = xcb_intern_atom(x11->c, 1, 12, "WM_PROTOCOLS"); + reply = xcb_intern_atom_reply(x11->c, cookie, 0); + + cookie = xcb_intern_atom(x11->c, 0, 16, "WM_DELETE_WINDOW"); + x11->dwcr = xcb_intern_atom_reply(x11->c, cookie, 0); + + xcb_change_property(x11->c, XCB_PROP_MODE_REPLACE, x11->w, reply->atom, 4, 32, 1, &x11->dwcr->atom); + +/*TODO: use xcb_request_check() for error handling. you need to call create_x11->wdwo_checked(). xxx_checked()... */ + xcb_map_window (x11->c, x11->w); xcb_flush (x11->c); - MOO_STACK_SETRET (moo, nargs, MOO_SMOOI_TO_OOP(win)); /* TODO: write this function to return a window handle... */ + MOO_STACK_SETRET (moo, nargs, MOO_SMOOI_TO_OOP(x11->w)); /* TODO: write this function to return a window handle... */ return MOO_PF_SUCCESS; }