added respondsTo: and perform:with:

fixed a bug in Dictionary>>__remove_at:
added gc callback to external modules
This commit is contained in:
hyunghwan.chung 2017-03-19 14:18:37 +00:00
parent 6a2add620b
commit 46ba3bb3f5
12 changed files with 550 additions and 136 deletions

34
moo/configure vendored
View File

@ -660,6 +660,8 @@ ENABLE_LIBLTDL_FALSE
ENABLE_LIBLTDL_TRUE
ENABLE_STATIC_MODULE_FALSE
ENABLE_STATIC_MODULE_TRUE
ENABLE_DYNAMIC_MODULE_FALSE
ENABLE_DYNAMIC_MODULE_TRUE
ENABLE_CXX_FALSE
ENABLE_CXX_TRUE
BUILD_MODE
@ -832,6 +834,7 @@ with_ltdl_lib
enable_ltdl_install
enable_debug
enable_cxx
enable_dynamic_module
enable_static_module
enable_libltdl
'
@ -1482,6 +1485,7 @@ Optional Features:
--enable-debug build the library in the debug mode (default. no)
--enable-cxx build the library for C++ if a C++ compiler is
available (default. yes)
--enable-dynamic-module enable dynamic module capability(default. yes)
--enable-static-module build modules statically into the main
library(default. no)
--enable-libltdl use libltdl(default. yes)
@ -20588,6 +20592,31 @@ else
fi
# Check whether --enable-dynamic-module was given.
if test "${enable_dynamic_module+set}" = set; then :
enableval=$enable_dynamic_module; enable_dynamic_module_is=$enableval
else
enable_dynamic_module_is=yes
fi
test "${enable_shared}" = "no" && enable_dynamic_module_is="no"
if test "${enable_dynamic_module_is}" = "yes"
then
$as_echo "#define MOO_ENABLE_DYNAMIC_MODULE /**/" >>confdefs.h
fi
if test "${enable_dynamic_module_is}" = "yes"; then
ENABLE_DYNAMIC_MODULE_TRUE=
ENABLE_DYNAMIC_MODULE_FALSE='#'
else
ENABLE_DYNAMIC_MODULE_TRUE='#'
ENABLE_DYNAMIC_MODULE_FALSE=
fi
# Check whether --enable-static-module was given.
if test "${enable_static_module+set}" = set; then :
enableval=$enable_static_module; enable_static_module_is=$enableval
@ -20613,7 +20642,6 @@ else
fi
# Check whether --enable-libltdl was given.
if test "${enable_libltdl+set}" = set; then :
enableval=$enable_libltdl; enable_libltdl_is=$enableval
@ -20844,6 +20872,10 @@ if test -z "${ENABLE_CXX_TRUE}" && test -z "${ENABLE_CXX_FALSE}"; then
as_fn_error $? "conditional \"ENABLE_CXX\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
if test -z "${ENABLE_DYNAMIC_MODULE_TRUE}" && test -z "${ENABLE_DYNAMIC_MODULE_FALSE}"; then
as_fn_error $? "conditional \"ENABLE_DYNAMIC_MODULE\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
if test -z "${ENABLE_STATIC_MODULE_TRUE}" && test -z "${ENABLE_STATIC_MODULE_FALSE}"; then
as_fn_error $? "conditional \"ENABLE_STATIC_MODULE\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5

View File

@ -420,6 +420,20 @@ test "${ax_cv_cxx_have_std_namespace}" = "yes" || enable_cxx_is="no"
AM_CONDITIONAL(ENABLE_CXX, test "${enable_cxx_is}" = "yes" )
dnl ===== enable-dynamic-module =====
AC_ARG_ENABLE([dynamic-module],
[AS_HELP_STRING([--enable-dynamic-module],[enable dynamic module capability(default. yes)])],
enable_dynamic_module_is=$enableval,
enable_dynamic_module_is=yes
)
test "${enable_shared}" = "no" && enable_dynamic_module_is="no"
if test "${enable_dynamic_module_is}" = "yes"
then
AC_DEFINE([MOO_ENABLE_DYNAMIC_MODULE],[],[enable dynamic module capability])
fi
AM_CONDITIONAL(ENABLE_DYNAMIC_MODULE, test "${enable_dynamic_module_is}" = "yes")
dnl ===== enable-static-module =====
AC_ARG_ENABLE([static-module],
[AS_HELP_STRING([--enable-static-module],[build modules statically into the main library(default. no)])],
@ -434,7 +448,6 @@ then
fi
AM_CONDITIONAL(ENABLE_STATIC_MODULE, test "${enable_static_module_is}" = "yes")
dnl ===== enable-libltdl =====
AC_ARG_ENABLE([libltdl],
[AS_HELP_STRING([--enable-libltdl],[use libltdl(default. yes)])],
@ -443,7 +456,7 @@ AC_ARG_ENABLE([libltdl],
)
if test "${enable_libltdl_is}" = "yes"
then
AC_DEFINE([MOO_ENABLE_LIBLTDL],[],[use libltdl])
AC_DEFINE([MOO_ENABLE_LIBLTDL],[],[use libltdl when loading a dynamic module])
fi
AM_CONDITIONAL(ENABLE_LIBLTDL, test "${enable_libltdl_is}" = "yes")

View File

@ -312,17 +312,86 @@ class Apex(nil)
^(self isMemberOf: aClass) or: [self class inheritsFrom: aClass].
}
(* -----------------
method(#class) respondsTo: selectorSymbol
## -------------------------------------------------------
## -------------------------------------------------------
method(#class) respondsTo: selector
{
TODO: find selectorSymbol in the class method dictionary...
<primitive: #_responds_to>
self primitiveFailed
}
method respondsTo: selectorSymbol
method respondsTo: selector
{
TODO: find selectorSymbol in the method dictionary...
<primitive: #_responds_to>
self primitiveFailed
}
------------ *)
## -------------------------------------------------------
## -------------------------------------------------------
method(#class) perform()
{
<primitive: #_perform>
self primitiveFailed
}
method perform()
{
<primitive: #_perform>
self primitiveFailed
}
method(#class) perform: selector
{
<primitive: #_perform>
self primitiveFailed
}
method perform: selector
{
<primitive: #_perform>
self primitiveFailed
}
method(#class) perform: selector with: arg1
{
<primitive: #_perform>
self primitiveFailed
}
method perform: selector with: arg1
{
<primitive: #_perform>
self primitiveFailed
}
method(#class) perform: selector with: arg1 with: arg2
{
<primitive: #_perform>
self primitiveFailed
}
method perform: selector with: arg1 with: arg2
{
<primitive: #_perform>
self primitiveFailed
}
method(#class) perform: selector with: arg1 with: arg2 with: arg3
{
<primitive: #_perform>
self primitiveFailed
}
method perform: selector with: arg1 with: arg2 with: arg3
{
<primitive: #_perform>
self primitiveFailed
}
## -------------------------------------------------------
## -------------------------------------------------------
method exceptionizeError: trueOrFalse
{

View File

@ -321,40 +321,33 @@ class Set(Collection)
method __remove_at: index
{
| bs x y i v |
| bs x y i v ass z |
bs := self.bucket size.
v := self.bucket basicAt: index.
v := self.bucket at: index.
x := index.
y := index.
i := 0.
[i < self.tally] whileTrue: [
| ass z |
while (i < self.tally)
{
y := (y + 1) rem: bs.
ass := self.bucket at: i.
if (ass isNil)
{
(* done. the slot at the current index is nil *)
i := self.tally
}
else
{
(* get the natural hash index *)
z := (ass key hash) rem: bs.
ass := self.bucket at: y.
if (ass isNil) { (* done. the slot at the current index is nil *) break }.
(* move an element if necessary *)
if ((y > x and: [(z <= x) or: [z > y]]) or: [(y < x) and: [(z <= x) and: [z > y]]])
{
self.bucket at: x put: (self.bucket at: y).
x := y.
}.
(* get the natural hash index *)
z := (ass key hash) rem: bs.
i := i + 1
(* move an element if necessary *)
if ((y > x and: [(z <= x) or: [z > y]]) or: [(y < x) and: [(z <= x) and: [z > y]]])
{
self.bucket at: x put: (self.bucket at: y).
x := y.
}.
].
i := i + 1.
}.
self.bucket at: x put: nil.
self.tally := self.tally - 1.
@ -744,14 +737,15 @@ class LinkedList(Collection)
else { self.first := link next }.
self.tally := self.tally - 1.
^link.
}
method removeFirst
method removeFirstLink
{
^self removeLink: self.first
}
method removeLast
method removeLastLink
{
^self removeLink: self.last
}
@ -767,4 +761,22 @@ class LinkedList(Collection)
link := next.
}
}
method doOverLink: block
{
| link next |
link := self.first.
while (link notNil)
{
next := link next.
block value: link.
link := next.
}
}
method findLink: value
{
self doOverLink: [:el | if (el value = value) { ^el }].
^Error.Code.ENOENT
}
}

View File

@ -108,6 +108,7 @@
#endif
static void signal_io_semaphore (moo_t* moo, int mask, void* ctx);
static int send_message (moo_t* moo, moo_oop_char_t selector, int to_super, moo_ooi_t nargs);
/* ------------------------------------------------------------------------- */
static MOO_INLINE int vm_startup (moo_t* moo)
@ -1521,6 +1522,7 @@ static moo_pfrc_t pf_basic_at (moo_t* moo, moo_ooi_t nargs)
if (!MOO_OOP_IS_POINTER(rcv))
{
/* the receiver is a special numeric object, not a normal pointer */
moo->errnum = MOO_EINVAL;
return MOO_PF_FAILURE;
}
@ -1528,11 +1530,13 @@ static moo_pfrc_t pf_basic_at (moo_t* moo, moo_ooi_t nargs)
if (moo_inttooow (moo, pos, &idx) <= 0)
{
/* negative integer or not integer */
moo->errnum = MOO_EINVAL;
return MOO_PF_FAILURE;
}
if (idx >= MOO_OBJ_GET_SIZE(rcv))
{
/* index out of range */
moo->errnum = MOO_ERANGE;
return MOO_PF_FAILURE;
}
@ -1580,6 +1584,7 @@ static moo_pfrc_t pf_basic_at_put (moo_t* moo, moo_ooi_t nargs)
if (!MOO_OOP_IS_POINTER(rcv))
{
/* the receiver is a special numeric object, not a normal pointer */
moo->errnum = MOO_EINVAL;
return MOO_PF_FAILURE;
}
pos = MOO_STACK_GETARG(moo, nargs, 0);
@ -1588,11 +1593,13 @@ static moo_pfrc_t pf_basic_at_put (moo_t* moo, moo_ooi_t nargs)
if (moo_inttooow (moo, pos, &idx) <= 0)
{
/* negative integer or not integer */
moo->errnum = MOO_EINVAL;
return MOO_PF_FAILURE;
}
if (idx >= MOO_OBJ_GET_SIZE(rcv))
{
/* index out of range */
moo->errnum = MOO_ERANGE;
return MOO_PF_FAILURE;
}
@ -1601,6 +1608,7 @@ static moo_pfrc_t pf_basic_at_put (moo_t* moo, moo_ooi_t nargs)
/* TODO: disallow change of some key kernel objects???? */
/* TODO: is it better to introduct a read-only mark in the object header instead of this class check??? */
/* read-only object */ /* TODO: DEVISE A WAY TO PASS a proper error from the primitive handler to MOO */
moo->errnum = MOO_EINVAL;
return MOO_PF_FAILURE;
}
@ -1610,6 +1618,7 @@ static moo_pfrc_t pf_basic_at_put (moo_t* moo, moo_ooi_t nargs)
if (!MOO_OOP_IS_SMOOI(val))
{
/* the value is not a character */
moo->errnum = MOO_EINVAL;
return MOO_PF_FAILURE;
}
/* TOOD: must I check the range of the value? */
@ -1620,6 +1629,7 @@ static moo_pfrc_t pf_basic_at_put (moo_t* moo, moo_ooi_t nargs)
if (!MOO_OOP_IS_CHAR(val))
{
/* the value is not a character */
moo->errnum = MOO_EINVAL;
return MOO_PF_FAILURE;
}
((moo_oop_char_t)rcv)->slot[idx] = MOO_OOP_TO_CHAR(val);
@ -1629,6 +1639,7 @@ static moo_pfrc_t pf_basic_at_put (moo_t* moo, moo_ooi_t nargs)
if (!MOO_OOP_IS_SMOOI(val))
{
/* the value is not a number */
moo->errnum = MOO_EINVAL;
return MOO_PF_FAILURE;
}
@ -1643,6 +1654,7 @@ static moo_pfrc_t pf_basic_at_put (moo_t* moo, moo_ooi_t nargs)
if (moo_inttooow (moo, val, &w) <= 0)
{
/* the value is not a number, out of range, or negative */
moo->errnum = MOO_EINVAL;
return MOO_PF_FAILURE;
}
((moo_oop_word_t)rcv)->slot[idx] = w;
@ -1712,6 +1724,7 @@ static moo_pfrc_t pf_hash (moo_t* moo, moo_ooi_t nargs)
default:
/* MOO_OBJ_TYPE_OOP, ... */
MOO_DEBUG1 (moo, "<pf_hash> Cannot hash an object of type %d\n", type);
moo->errnum = MOO_EINVAL;
return MOO_PF_FAILURE;
}
break;
@ -1726,6 +1739,65 @@ static moo_pfrc_t pf_hash (moo_t* moo, moo_ooi_t nargs)
return MOO_PF_SUCCESS;
}
static moo_pfrc_t pf_responds_to (moo_t* moo, moo_ooi_t nargs)
{
moo_oop_t rcv, selector;
moo_oocs_t mthname;
rcv = MOO_STACK_GETRCV(moo, nargs);
selector = MOO_STACK_GETARG(moo, nargs, 0);
if (MOO_CLASSOF(moo,selector) != moo->_symbol)
{
moo->errnum = MOO_EINVAL;
return MOO_PF_FAILURE;
}
mthname.ptr = MOO_OBJ_GET_CHAR_SLOT(selector);
mthname.len = MOO_OBJ_GET_SIZE(selector);
if (find_method (moo, rcv, &mthname, 0))
{
MOO_STACK_SETRET (moo, nargs, moo->_true);
}
else
{
MOO_STACK_SETRET (moo, nargs, moo->_false);
}
return MOO_PF_SUCCESS;
}
static moo_pfrc_t pf_perform (moo_t* moo, moo_ooi_t nargs)
{
moo_oop_t /*rcv,*/ selector;
moo_oow_t ssp, esp, i;
/*rcv = MOO_STACK_GETRCV(moo, nargs);*/
selector = MOO_STACK_GETARG(moo, nargs, 0);
if (MOO_CLASSOF(moo,selector) != moo->_symbol)
{
moo->errnum = MOO_EINVAL;
return MOO_PF_FAILURE;
}
/* remove the selector from the stack */
ssp = MOO_STACK_GETARGSP (moo, nargs, 0);
esp = MOO_STACK_GETARGSP (moo, nargs, nargs - 1);
for (i = ssp; i < esp;)
{
moo_oop_t t;
t = MOO_STACK_GET (moo, i);
i++;
MOO_STACK_SET(moo, i, t);
}
MOO_STACK_POP (moo);
/* emulate message sending */
if (send_message (moo, (moo_oop_char_t)selector, 0, nargs - 1) <= -1) return MOO_PF_HARD_FAILURE;
return MOO_PF_SUCCESS;
}
static moo_pfrc_t pf_exceptionize_error (moo_t* moo, moo_ooi_t nargs)
{
moo_oop_t rcv;
@ -2719,12 +2791,15 @@ static pf_t pftab[] =
{ 0, 0, pf_hash, "_hash" },
{ 1, 1, pf_responds_to, "_responds_to" },
{ 1, MAX_NARGS, pf_perform, "_perform" },
{ 1, 1, pf_exceptionize_error, "_exceptionize_error" },
{ 1, 1, pf_context_goto, "_context_goto" },
{ 0, MAX_NARGS, pf_block_value, "_block_value" },
{ 0, MAX_NARGS, pf_block_new_process, "_block_new_process" },
{ 0, 0, pf_process_resume, "_process_resume" },
{ 0, 0, pf_process_terminate, "_process_terminate" },
{ 0, 0, pf_process_yield, "_process_yield" },
@ -3043,7 +3118,7 @@ static int send_message (moo_t* moo, moo_oop_char_t selector, int to_super, moo_
receiver = MOO_STACK_GET(moo, moo->sp - nargs);
mthname.ptr = selector->slot;
mthname.ptr = MOO_OBJ_GET_CHAR_SLOT(selector);
mthname.len = MOO_OBJ_GET_SIZE(selector);
method = find_method (moo, receiver, &mthname, to_super);
if (!method)

View File

@ -562,6 +562,19 @@ static moo_uint8_t* scan_new_heap (moo_t* moo, moo_uint8_t* ptr)
return ptr;
}
static moo_rbt_walk_t call_module_gc (moo_rbt_t* rbt, moo_rbt_pair_t* pair, void* ctx)
{
moo_t* moo = (moo_t*)ctx;
moo_mod_data_t* mdp;
mdp = MOO_RBT_VPTR(pair);
MOO_ASSERT (moo, mdp != MOO_NULL);
if (mdp->mod.gc) mdp->mod.gc (moo, &mdp->mod);
return MOO_RBT_WALK_FORWARD;
}
void moo_gc (moo_t* moo)
{
/*
@ -643,6 +656,8 @@ void moo_gc (moo_t* moo)
if (moo->active_method)
moo->active_method = (moo_oop_method_t)moo_moveoop (moo, (moo_oop_t)moo->active_method);
moo_rbt_walk (&moo->modtab, call_module_gc, moo);
for (cb = moo->cblist; cb; cb = cb->next)
{
if (cb->gc) cb->gc (moo);

View File

@ -462,6 +462,9 @@ static void* dl_open (moo_t* moo, const moo_ooch_t* name, int flags)
return handle;
#else
/* TODO: support various platforms */
/* TODO: implemenent this */
MOO_DEBUG1 (moo, "Dynamic loading not implemented - cannot open %js\n", name);
@ -1320,11 +1323,12 @@ int main (int argc, char* argv[])
}
#endif
memset (&vmprim, 0, MOO_SIZEOF(vmprim));
vmprim.dl_open = dl_open;
vmprim.dl_close = dl_close;
vmprim.dl_getsym = dl_getsym;
vmprim.log_write = log_write;
vmprim.vm_startup = vm_startup;
vmprim.vm_cleanup = vm_cleanup;
vmprim.vm_gettime = vm_gettime;

View File

@ -326,7 +326,10 @@
/* Define to the shared archive member specification, say "(shr.o)". */
#undef LT_SHARED_LIB_MEMBER
/* use libltdl */
/* enable dynamic module capability */
#undef MOO_ENABLE_DYNAMIC_MODULE
/* use libltdl when loading a dynamic module */
#undef MOO_ENABLE_LIBLTDL
/* link modules statically into the main library */

View File

@ -925,15 +925,6 @@ void* moo_allocheapmem (
moo_oow_t size
);
/* ========================================================================= */
/* gc.c */
/* ========================================================================= */
moo_oop_t moo_moveoop (
moo_t* moo,
moo_oop_t oop
);
/* ========================================================================= */
/* obj.c */
/* ========================================================================= */
@ -1185,13 +1176,14 @@ int moo_getpfnum (
/* ========================================================================= */
/* moo.c */
/* moo.c */
/* ========================================================================= */
moo_mod_data_t* moo_openmod (
moo_t* moo,
const moo_ooch_t* name,
moo_oow_t namelen
moo_oow_t namelen,
int hints /* 0 or bitwise-ORed of moo_mod_hint_t enumerators */
);
void moo_closemod (

View File

@ -378,7 +378,7 @@ static_modtab[] =
};
#endif
moo_mod_data_t* moo_openmod (moo_t* moo, const moo_ooch_t* name, moo_oow_t namelen)
moo_mod_data_t* moo_openmod (moo_t* moo, const moo_ooch_t* name, moo_oow_t namelen, int hints)
{
moo_rbt_pair_t* pair;
moo_mod_data_t* mdp;
@ -423,14 +423,6 @@ moo_mod_data_t* moo_openmod (moo_t* moo, const moo_ooch_t* name, moo_oow_t namel
}
}
if (n >= MOO_COUNTOF(static_modtab))
{
MOO_DEBUG2 (moo, "Cannot find a static module [%.*js]\n", namelen, name);
moo->errnum = MOO_ENOENT;
return MOO_NULL;
/* TODO: fall back to find dynamic module further on supported platforms instead of returning error here... */
}
if (load)
{
/* found the module in the staic module table */
@ -449,17 +441,36 @@ moo_mod_data_t* moo_openmod (moo_t* moo, const moo_ooch_t* name, moo_oow_t namel
}
mdp = (moo_mod_data_t*)MOO_RBT_VPTR(pair);
MOO_ASSERT (moo, MOO_SIZEOF(mdp->mod.hints) == MOO_SIZEOF(int));
*(int*)&mdp->mod.hints = hints;
if (load (moo, &mdp->mod) <= -1)
{
moo_rbt_delete (&moo->modtab, (moo_ooch_t*)name, namelen);
return MOO_NULL;
}
mdp->pair = pair;
MOO_DEBUG1 (moo, "Opened a static module [%js]\n", mdp->mod.name);
return mdp;
}
else
{
#if !defined(MOO_ENABLE_DYNAMIC_MODULE)
MOO_DEBUG2 (moo, "Cannot find a static module [%.*js]\n", namelen, name);
moo->errnum = MOO_ENOENT;
return MOO_NULL;
#endif
}
#endif
/* attempt to find an external module */
#if !defined(MOO_ENABLE_DYNAMIC_MODULE)
MOO_DEBUG2 (moo, "Cannot open module [%.*js] - module loading disabled\n", namelen, name);
moo->errnum = MOO_ENOIMPL; /* TODO: is it a good error number for disabled module loading? */
return MOO_NULL;
#endif
/* attempt to find a dynamic external module */
MOO_MEMSET (&md, 0, MOO_SIZEOF(md));
moo_copyoochars ((moo_ooch_t*)md.mod.name, name, namelen);
if (moo->vmprim.dl_open && moo->vmprim.dl_getsym && moo->vmprim.dl_close)
@ -496,6 +507,8 @@ moo_mod_data_t* moo_openmod (moo_t* moo, const moo_ooch_t* name, moo_oow_t namel
}
mdp = (moo_mod_data_t*)MOO_RBT_VPTR(pair);
MOO_ASSERT (moo, MOO_SIZEOF(mdp->mod.hints) == MOO_SIZEOF(int));
*(int*)&mdp->mod.hints = hints;
if (load (moo, &mdp->mod) <= -1)
{
MOO_DEBUG3 (moo, "Module function [%js] returned failure in [%.*js]\n", buf, namelen, name);
@ -525,6 +538,10 @@ void moo_closemod (moo_t* moo, moo_mod_data_t* mdp)
MOO_DEBUG2 (moo, "Closed a module [%js] - %p\n", mdp->mod.name, mdp->handle);
mdp->handle = MOO_NULL;
}
else
{
MOO_DEBUG1 (moo, "Closed a static module [%js] - %p\n", mdp->mod.name);
}
if (mdp->pair)
{
@ -537,7 +554,7 @@ int moo_importmod (moo_t* moo, moo_oop_class_t _class, const moo_ooch_t* name, m
{
moo_rbt_pair_t* pair;
moo_mod_data_t* mdp;
int r = 0;
int r = -1;
/* moo_openmod(), moo_closemod(), etc call a user-defined callback.
* i need to protect _class in case the user-defined callback allocates
@ -550,38 +567,36 @@ int moo_importmod (moo_t* moo, moo_oop_class_t _class, const moo_ooch_t* name, m
{
mdp = (moo_mod_data_t*)MOO_RBT_VPTR(pair);
MOO_ASSERT (moo, mdp != MOO_NULL);
MOO_DEBUG1 (moo, "Cannot import module [%js] - already active\n", mdp->mod.name);
moo->errnum = MOO_EPERM;
goto done2;
}
else
{
mdp = moo_openmod (moo, name, len);
if (!mdp)
{
r = -1;
goto done2;
}
}
mdp = moo_openmod (moo, name, len, MOO_MOD_LOAD_FOR_IMPORT);
if (!mdp) goto done2;
if (!mdp->mod.import)
{
MOO_DEBUG1 (moo, "Cannot import module [%js] - importing not supported by the module\n", mdp->mod.name);
moo->errnum = MOO_ENOIMPL;
r = -1;
goto done;
}
if (mdp->mod.import (moo, &mdp->mod, _class) <= -1)
{
MOO_DEBUG1 (moo, "Cannot import module [%js] - module's import() returned failure\n", mdp->mod.name);
r = -1;
goto done;
}
r = 0; /* everything successful */
done:
if (!pair)
{
/* close the module if it has been opened in this function. */
moo_closemod (moo, mdp);
}
/* close the module opened above.
* [NOTE] if the import callback calls the moo_querymod(), the returned
* function pointers will get all invalidated here. so never do
* anything like that */
moo_closemod (moo, mdp);
done2:
moo_poptmp (moo);
@ -615,8 +630,8 @@ moo_pfimpl_t moo_querymod (moo_t* moo, const moo_ooch_t* pfid, moo_oow_t pfidlen
mod_name_len = sep - pfid;
/* the first through the segment before the last compose a module id.
* the last segment is the primitive function name.
/* the first segment through the segment before the last compose a
* module id. the last segment is the primitive function name.
* for instance, in con.window.open, con.window is a module id and
* open is the primitive function name. */
pair = moo_rbt_search (&moo->modtab, pfid, mod_name_len);
@ -628,7 +643,7 @@ moo_pfimpl_t moo_querymod (moo_t* moo, const moo_ooch_t* pfid, moo_oow_t pfidlen
else
{
/* open a module using the part before the last period */
mdp = moo_openmod (moo, pfid, mod_name_len);
mdp = moo_openmod (moo, pfid, mod_name_len, 0);
if (!mdp) return MOO_NULL;
}
@ -873,3 +888,22 @@ void* moo_getobjtrailer (moo_t* moo, moo_oop_t obj, moo_oow_t* size)
if (size) *size = MOO_OBJ_GET_TRAILER_SIZE(obj);
return MOO_OBJ_GET_TRAILER_BYTE(obj);
}
moo_oop_t moo_findclass (moo_t* moo, moo_oop_set_t nsdic, const moo_ooch_t* name)
{
moo_oop_association_t ass;
moo_oocs_t n;
n.ptr = (moo_ooch_t*)name;
n.len = moo_countoocstr(name);
ass = moo_lookupdic (moo, nsdic, &n);
if (!ass || MOO_CLASSOF(moo,ass->value) != moo->_class)
{
moo->errnum = MOO_ENOENT;
return MOO_NULL;
}
return ass->value;
}

View File

@ -840,9 +840,14 @@ struct moo_pfinfo_t
moo_pfimpl_t handler;
};
typedef struct moo_mod_t moo_mod_t;
enum moo_mod_hint_t
{
MOO_MOD_LOAD_FOR_IMPORT = (1 << 0)
};
typedef enum moo_mod_hint_t moo_mod_hint_t;
typedef int (*moo_mod_load_t) (
moo_t* moo,
moo_mod_t* mod
@ -865,12 +870,22 @@ typedef void (*moo_mod_unload_t) (
moo_mod_t* mod
);
typedef void (*moo_mod_gc_t) (
moo_t* moo,
moo_mod_t* mod
);
struct moo_mod_t
{
/* input */
const moo_ooch_t name[MOO_MOD_NAME_LEN_MAX + 1];
const int hints; /* bitwised-ORed of moo_mod_hint_t enumerators */
/* user-defined data */
moo_mod_import_t import;
moo_mod_query_t query;
moo_mod_unload_t unload;
moo_mod_gc_t gc;
void* ctx;
};
@ -883,7 +898,6 @@ struct moo_mod_data_t
typedef struct moo_mod_data_t moo_mod_data_t;
struct moo_sbuf_t
{
moo_ooch_t* ptr;
@ -1065,6 +1079,7 @@ struct moo_t
#define MOO_STACK_POPS(moo,count) ((moo)->sp = (moo)->sp - (count))
#define MOO_STACK_ISEMPTY(moo) ((moo)->sp <= -1)
#define MOO_STACK_GETARGSP(moo,nargs,idx) ((moo)->sp - ((nargs) - (idx) - 1))
#define MOO_STACK_GETARG(moo,nargs,idx) MOO_STACK_GET(moo, (moo)->sp - ((nargs) - (idx) - 1))
#define MOO_STACK_GETRCV(moo,nargs) MOO_STACK_GET(moo, (moo)->sp - nargs)
@ -1348,6 +1363,15 @@ MOO_EXPORT void moo_gc (
);
/**
* The moo_moveoop() function moves an object and returns an updated pointer
* after having moved. it must be called in the GC callback context only.
*/
MOO_EXPORT moo_oop_t moo_moveoop (
moo_t* moo,
moo_oop_t oop
);
/**
* The moo_instantiate() function creates a new object instance of the class
* \a _class. The size of the fixed part is taken from the information
@ -1457,6 +1481,11 @@ MOO_EXPORT int moo_inttoooi (
moo_ooi_t* i
);
MOO_EXPORT moo_oop_t moo_findclass (
moo_t* moo,
moo_oop_set_t nsdic,
const moo_ooch_t* name
);
/* =========================================================================
* TRAILER MANAGEMENT

View File

@ -34,12 +34,21 @@
#define C MOO_METHOD_CLASS
#define I MOO_METHOD_INSTANCE
typedef struct x11_modctx_t x11_modctx_t;
struct x11_modctx_t
{
moo_oop_class_t x11_class;
moo_oop_class_t mouse_event_class;
moo_oop_class_t key_event_class;
};
typedef struct x11_t x11_t;
struct x11_t
{
xcb_connection_t* c;
xcb_screen_t* screen;
xcb_generic_event_t* curevt; /* most recent event received */
};
typedef struct x11_win_t x11_win_t;
@ -49,6 +58,7 @@ struct x11_win_t
xcb_intern_atom_reply_t* dwcr;
};
/* ------------------------------------------------------------------------ */
static moo_pfrc_t pf_connect (moo_t* moo, moo_ooi_t nargs)
@ -56,6 +66,8 @@ static moo_pfrc_t pf_connect (moo_t* moo, moo_ooi_t nargs)
x11_t* x11;
xcb_connection_t* c;
x11 = (x11_t*)moo_getobjtrailer(moo, MOO_STACK_GETRCV(moo, nargs), MOO_NULL);
/* TODO: accept display target as a parameter */
if (nargs != 0)
{
@ -63,8 +75,6 @@ static moo_pfrc_t pf_connect (moo_t* moo, moo_ooi_t nargs)
goto softfail;
}
x11 = (x11_t*)moo_getobjtrailer(moo, MOO_STACK_GETRCV(moo, nargs), MOO_NULL);
if (x11->c)
{
MOO_DEBUG0 (moo, "<x11.connect> Unable to connect multiple times\n");
@ -108,6 +118,11 @@ static moo_pfrc_t pf_disconnect (moo_t* moo, moo_ooi_t nargs)
MOO_DEBUG1 (moo, "<x11.disconnect> %p\n", x11->c);
if (x11->curevt)
{
free (x11->curevt);
x11->curevt = MOO_NULL;
}
if (x11->c)
{
xcb_disconnect (x11->c);
@ -116,18 +131,14 @@ static moo_pfrc_t pf_disconnect (moo_t* moo, moo_ooi_t nargs)
MOO_STACK_SETRETTORCV (moo, nargs);
return MOO_PF_SUCCESS;
softfail:
MOO_STACK_SETRETTOERROR (moo, nargs);
return MOO_PF_SUCCESS;
}
static moo_pfrc_t pf_getfd (moo_t* moo, moo_ooi_t nargs)
static moo_pfrc_t pf_get_fd (moo_t* moo, moo_ooi_t nargs)
{
x11_t* x11;
x11 = (x11_t*)moo_getobjtrailer(moo, MOO_STACK_GETRCV(moo, nargs), MOO_NULL);
MOO_DEBUG1 (moo, "<x11.getfd> %p\n", x11->c);
MOO_DEBUG1 (moo, "<x11.get_fd> %p\n", x11->c);
if (x11->c)
{
@ -146,38 +157,73 @@ static moo_pfrc_t pf_getfd (moo_t* moo, moo_ooi_t nargs)
return MOO_PF_SUCCESS;
}
static moo_pfrc_t pf_getevent (moo_t* moo, moo_ooi_t nargs)
{
x11_t* x11;
xcb_generic_event_t* evt;
x11 = (x11_t*)moo_getobjtrailer(moo, MOO_STACK_GETRCV(moo, nargs), MOO_NULL);
MOO_DEBUG1 (moo, "<x11.__getevent> %p\n", x11->c);
MOO_DEBUG1 (moo, "<x11.getevent> %p\n", x11->c);
evt = xcb_poll_for_event(x11->c);
if (x11->curevt) free (x11->curevt);
x11->curevt = evt;
if (evt)
{
uint8_t evttype = evt->response_type & ~0x80;
uint8_t evttype = evt->response_type & 0x7F;
x11->curevt = evt;
if (evttype == XCB_CLIENT_MESSAGE)
#if 0
&&
((xcb_client_message_event_t*)evt)->data.data32[0] == x11->dwcr->atom)
#endif
{
#if 0
xcb_unmap_window (x11->c, x11->w);
xcb_destroy_window (x11->c, x11->w);
xcb_flush (x11->c);
#endif
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 */
}
#if 0
switch (evttype)
{
case XCB_CLIENT_MESSAGE:
#if 0
if (((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);
}
#endif
MOO_STACK_SETRET (moo, nargs, MOO_SMOOI_TO_OOP(9999)); /* TODO: translate evt to the event object */
break;
case XCB_BUTTON_PRESS:
case XCB_BUTTON_RELEASE:
{
xcb_button_press_event_t* bpe = (xcb_button_press_event_t*)evt;
MOO_STACK_SETRET (moo, nargs, e);
break;
}
default:
MOO_STACK_SETRET (moo, nargs, MOO_SMOOI_TO_OOP(evttype)); /* TODO: translate evt to the event object */
break;
}
free (evt);
#endif
}
else if (xcb_connection_has_error(x11->c))
{
/* TODO: to be specific about the error */
MOO_STACK_SETRETTOERROR (moo, nargs);
}
else
{
@ -189,23 +235,72 @@ static moo_pfrc_t pf_getevent (moo_t* moo, moo_ooi_t nargs)
/* ------------------------------------------------------------------------ */
static moo_pfrc_t pf_win_get_id (moo_t* moo, moo_ooi_t nargs)
{
x11_win_t* win;
moo_oop_t x;
win = (x11_win_t*)moo_getobjtrailer(moo, MOO_STACK_GETRCV(moo, nargs), MOO_NULL);
x = moo_oowtoint (moo, win->id);
if (!x) return MOO_PF_HARD_FAILURE;
MOO_STACK_SETRET (moo, nargs, x);
return MOO_PF_SUCCESS;
}
static moo_pfrc_t pf_win_kill_on (moo_t* moo, moo_ooi_t nargs)
{
x11_t* x11;
x11_win_t* win;
x11 = (x11_t*)moo_getobjtrailer(moo, MOO_STACK_GETARG(moo, nargs, 0), MOO_NULL);
win = (x11_win_t*)moo_getobjtrailer(moo, MOO_STACK_GETRCV(moo, nargs), MOO_NULL);
if (!x11->c)
{
MOO_STACK_SETRETTOERROR (moo, nargs); /* More specific error code*/
return MOO_PF_SUCCESS;
}
/* TODO: check on windows id */
xcb_unmap_window (x11->c, win->id); /* TODO: check error code */
xcb_destroy_window (x11->c, win->id);
xcb_flush (x11->c);
MOO_STACK_SETRETTORCV (moo, nargs);
return MOO_PF_SUCCESS;
}
static moo_pfrc_t pf_win_make_on (moo_t* moo, moo_ooi_t nargs)
{
x11_t* x11;
x11_win_t* win;
moo_oop_t id;
uint32_t mask;
uint32_t values[2];
xcb_intern_atom_cookie_t cookie;
xcb_intern_atom_reply_t* reply;
MOO_DEBUG0 (moo, "<x11.win._makeon:> %p\n");
MOO_DEBUG0 (moo, "<x11.win._make_on:> %p\n");
x11 = (x11_t*)moo_getobjtrailer(moo, MOO_STACK_GETARG(moo, nargs, 0), MOO_NULL);
win = (x11_win_t*)moo_getobjtrailer(moo, MOO_STACK_GETRCV(moo, nargs), MOO_NULL);
if (!x11->c)
{
MOO_STACK_SETRETTOERROR (moo, nargs); /* TODO: be more specific about error */
return MOO_PF_SUCCESS;
}
win->id = xcb_generate_id (x11->c);
id = moo_oowtoint (moo, win->id);
if (!id) return MOO_PF_HARD_FAILURE;
mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
values[0] = x11->screen->white_pixel;
values[1] = XCB_EVENT_MASK_KEY_RELEASE |
@ -237,44 +332,20 @@ MOO_DEBUG0 (moo, "<x11.win._makeon:> %p\n");
xcb_map_window (x11->c, win->id);
xcb_flush (x11->c);
MOO_STACK_SETRETTORCV (moo, nargs);
MOO_STACK_SETRET (moo, nargs, id);
return MOO_PF_SUCCESS;
}
static moo_pfrc_t pf_win_kill_on (moo_t* moo, moo_ooi_t nargs)
{
x11_t* x11;
x11_win_t* win;
x11 = (x11_t*)moo_getobjtrailer(moo, MOO_STACK_GETARG(moo, nargs, 0), MOO_NULL);
win = (x11_win_t*)moo_getobjtrailer(moo, MOO_STACK_GETRCV(moo, nargs), MOO_NULL);
if (!x11->c)
{
MOO_STACK_SETRETTOERROR (moo, nargs); /* More specific error code*/
return MOO_PF_SUCCESS;
}
/* TODO: check on windows id */
xcb_unmap_window (x11->c, win->id); /* TODO: check error code */
xcb_destroy_window (x11->c, win->id);
xcb_flush (x11->c);
MOO_STACK_SETRETTORCV (moo, nargs);
return MOO_PF_SUCCESS;
}
/* ------------------------------------------------------------------------ */
static moo_pfinfo_t x11_pfinfo[] =
{
{ I, { '_','g','e','t','e','v','e','n','t','\0'}, 0, pf_getevent },
{ I, { 'c','o','n','n','e','c','t','\0' }, 0, pf_connect },
{ I, { 'd','i','s','c','o','n','n','e','c','t','\0' }, 0, pf_disconnect },
{ I, { 'g','e','t','f','d','\0' }, 0, pf_getfd }
{ I, { '_','c','o','n','n','e','c','t','\0' }, 0, pf_connect },
{ I, { '_','d','i','s','c','o','n','n','e','c','t','\0' }, 0, pf_disconnect },
{ I, { '_','g','e','t','_','e','v','e','n','t','\0'}, 0, pf_getevent },
{ I, { '_','g','e','t','_','f','d','\0' }, 0, pf_get_fd }
};
static int x11_import (moo_t* moo, moo_mod_t* mod, moo_oop_class_t _class)
@ -291,15 +362,77 @@ static moo_pfimpl_t x11_query (moo_t* moo, moo_mod_t* mod, const moo_ooch_t* nam
static void x11_unload (moo_t* moo, moo_mod_t* mod)
{
/* TODO: anything? close open open dll handles? For that, pf_open must store the value it returns to mod->ctx or somewhere..*/
/* TODO: anything else? close all open dll handles? For that, pf_open must store the value it returns to mod->ctx or somewhere..*/
moo_freemem (moo, mod->ctx);
}
static void x11_gc (moo_t* moo, moo_mod_t* mod)
{
x11_modctx_t* ctx = mod->ctx;
MOO_ASSERT (moo, ctx != MOO_NULL);
ctx->mouse_event_class = (moo_oop_class_t)moo_moveoop (moo, (moo_oop_t)ctx->mouse_event_class);
ctx->key_event_class = (moo_oop_class_t)moo_moveoop (moo, (moo_oop_t)ctx->key_event_class);
}
int moo_mod_x11 (moo_t* moo, moo_mod_t* mod)
{
if (mod->hints & MOO_MOD_LOAD_FOR_IMPORT)
{
mod->gc = MOO_NULL;
mod->ctx = MOO_NULL;
}
else
{
x11_modctx_t* ctx;
static moo_ooch_t name_x11[] = { 'X','1','1','\0' };
static moo_ooch_t name_mouse_event[] = { 'M','o','u','s','e','E','v','e','n','t','\0' };
static moo_ooch_t name_key_event[] = { 'K','e','y','E','v','e','n','t','\0' };
ctx = moo_callocmem (moo, MOO_SIZEOF(*ctx));
if (!ctx) return -1;
ctx->x11_class = (moo_oop_class_t)moo_findclass (moo, moo->sysdic, name_x11);
if (!ctx->x11_class)
{
/* Not a single X11.XXX has been defined. */
MOO_DEBUG0 (moo, "X11 class not found\n");
oops:
moo_freemem (moo, ctx);
return -1;
}
if ((moo_oop_t)ctx->x11_class->nsdic == moo->_nil)
{
MOO_DEBUG0 (moo, "No class defined in X11\n");
goto oops;
}
/* TODO: check on instance size... etc */
/* TODO: tabulate key event classes */
ctx->mouse_event_class = (moo_oop_class_t)moo_findclass (moo, ctx->x11_class->nsdic, name_mouse_event);
if (!ctx->mouse_event_class)
{
MOO_DEBUG0 (moo, "X11.MouseEvent class not found\n");
goto oops;
}
ctx->key_event_class = (moo_oop_class_t)moo_findclass (moo, ctx->x11_class->nsdic, name_key_event);
if (!ctx->key_event_class)
{
MOO_DEBUG0 (moo, "X11.KeyEvent class not found\n");
goto oops;
}
mod->gc = x11_gc;
mod->ctx = ctx;
}
mod->import = x11_import;
mod->query = x11_query;
mod->unload = x11_unload;
mod->ctx = MOO_NULL;
return 0;
}
@ -307,8 +440,9 @@ int moo_mod_x11 (moo_t* moo, moo_mod_t* mod)
static moo_pfinfo_t x11_win_pfinfo[] =
{
{ I, { '_','m','a','k','e','_','o','n',':','\0' }, 0, pf_win_make_on },
{ I, { '_','k','i','l','l','_','o','n',':','\0' }, 0, pf_win_kill_on }
{ I, { '_','g','e','t','_','i','d','\0' }, 0, pf_win_get_id },
{ I, { '_','k','i','l','l','_','o','n',':','\0' }, 0, pf_win_kill_on },
{ I, { '_','m','a','k','e','_','o','n',':','\0' }, 0, pf_win_make_on }
};
static int x11_win_import (moo_t* moo, moo_mod_t* mod, moo_oop_class_t _class)
@ -325,7 +459,7 @@ static moo_pfimpl_t x11_win_query (moo_t* moo, moo_mod_t* mod, const moo_ooch_t*
static void x11_win_unload (moo_t* moo, moo_mod_t* mod)
{
/* TODO: anything? */
/* anything? */
}
int moo_mod_x11_win (moo_t* moo, moo_mod_t* mod)
@ -333,6 +467,8 @@ int moo_mod_x11_win (moo_t* moo, moo_mod_t* mod)
mod->import = x11_win_import;
mod->query = x11_win_query;
mod->unload = x11_win_unload;
mod->gc = MOO_NULL;
mod->ctx = MOO_NULL;
return 0;
}