extended module query facility to find primitive value(querypv) as well as primitive function(querypf)

This commit is contained in:
hyunghwan.chung 2019-10-25 08:44:05 +00:00
parent dde69fb64e
commit 484f5ef7f9
15 changed files with 209 additions and 66 deletions

View File

@ -1,6 +1,6 @@
class(#limited) InputOutputStud(Object) from "io"
{
var(#get) handle. // you must keep handle as the first field for consitency with the 'io' module.
var(#get) handle. // you must keep handle as the first field for consitency with the io module.
method(#primitive,#lenient) _close.
method(#primitive) _readBytesInto: buffer startingAt: offset for: count.
@ -11,10 +11,11 @@ class FileAccessor(InputOutputStud) from "io.file"
{
pooldic Flag
{
O_RDONLY := 0,
O_WRONLY := 1
//O_RDONLY from "O_RDONLY",
//O_WRONLY from "O_WRONLY"
//O_RDONLY := 0,
//O_WRONLY := 1
O_RDONLY from "io.file.O_RDONLY",
O_WRONLY from "io.file.O_WRONLY",
O_RDWR from "io.file.O_RDWR"
}
method(#primitive,#lenient) _open: path flags: flags.

View File

@ -4416,7 +4416,7 @@ static int compile_method_pragma (moo_t* moo)
/* external named primitive containing a period. */
/* perform some sanity checks. see compile_method_definition() for similar checks */
pfbase = moo_querymod(moo, tptr, tlen, MOO_NULL);
pfbase = moo_querymodpf(moo, tptr, tlen, MOO_NULL);
if (!pfbase)
{
MOO_DEBUG2 (moo, "Cannot find module primitive function - %.*js\n", tlen, tptr);
@ -8137,7 +8137,7 @@ static int resolve_primitive_method (moo_t* moo)
/* check if the primitive function exists at the compile time and perform some checks.
* see compile_method_primitive() for similar checks */
pfbase = moo_querymod(moo, &cc->modname.ptr[savedlen], cc->modname.len - savedlen, MOO_NULL);
pfbase = moo_querymodpf(moo, &cc->modname.ptr[savedlen], cc->modname.len - savedlen, MOO_NULL);
if (!pfbase)
{
MOO_DEBUG2 (moo, "Cannot find module primitive function - %.*js\n",
@ -10192,17 +10192,68 @@ static int __compile_pooldic_definition (moo_t* moo)
GET_TOKEN (moo);
if (TOKEN_TYPE(moo) != MOO_IOTOK_ASSIGN)
if (TOKEN_TYPE(moo) == MOO_IOTOK_IDENT && is_token_word(moo, VOCA_FROM))
{
moo_pvbase_t* pvbase;
/*
* pooldic X {
* O_RDONLY := 0,
* O_WRONLY from "O_WRONLY"
* }
*/
/* TODO: check if this pooldic definition is nested inside a class */
/* TODO: make it more robust */
GET_TOKEN (moo);
if (TOKEN_TYPE(moo) != MOO_IOTOK_STRLIT)
{
moo_setsynerrbfmt (moo, MOO_SYNERR_STRING, TOKEN_LOC(moo), TOKEN_NAME(moo), "primitive value name to import expected");
goto oops;
}
pvbase = moo_querymodpv(moo, TOKEN_NAME_PTR(moo), TOKEN_NAME_LEN(moo), MOO_NULL);
if (!pvbase)
{
/* TODO: backup error message and use it */
moo_setsynerrbfmt (moo, MOO_SYNERR_STRING, TOKEN_LOC(moo), TOKEN_NAME(moo), "primitive value name unknown");
goto oops;
}
switch (pvbase->type)
{
case MOO_PV_INT:
{
moo_oocs_t x;
x.ptr = moo_dupbtooocstr(moo, pvbase->vstr, &x.len);
if (!x.ptr) goto oops;
tmp = string_to_int(moo, &x, 0);
moo_freemem (moo, x.ptr);
if (tmp && MOO_OOP_IS_POINTER(tmp)) MOO_OBJ_SET_FLAGS_RDONLY (tmp, 1);
break;
}
default:
moo_setsynerrbfmt (moo, MOO_SYNERR_STRING, TOKEN_LOC(moo), TOKEN_NAME(moo), "unsupported pvtype");
goto oops;
}
if (!tmp) goto oops;
}
else if (TOKEN_TYPE(moo) == MOO_IOTOK_ASSIGN)
{
GET_TOKEN (moo);
tmp = token_to_literal(moo, 1);
if (!tmp) goto oops;
}
else
{
moo_setsynerr (moo, MOO_SYNERR_ASSIGN, TOKEN_LOC(moo), TOKEN_NAME(moo));
goto oops;
}
GET_TOKEN (moo);
tmp = token_to_literal(moo, 1);
if (!tmp) goto oops;
/* for this definition, #pooldic MyPoolDic { a := 10. b := 20 },
* arlit_buffer contains (#a 10 #b 20) when the 'while' loop is over. */
if (add_to_array_literal_buffer(moo, tmp) <= -1) goto oops;

View File

@ -4738,10 +4738,10 @@ static int start_method (moo_t* moo, moo_oop_method_t method, moo_oow_t nargs)
if (pfbase)
{
mod = MOO_OOP_TO_SMPTR(method->preamble_data[0]);
goto exec_handler; /* skip moo_querymod() */
goto exec_handler; /* skip moo_querymodpf() */
}
pfbase = moo_querymod(moo, MOO_OBJ_GET_CHAR_SLOT(pfname), MOO_OBJ_GET_SIZE(pfname), &mod);
pfbase = moo_querymodpf(moo, MOO_OBJ_GET_CHAR_SLOT(pfname), MOO_OBJ_GET_SIZE(pfname), &mod);
if (pfbase)
{
int n;

View File

@ -1049,4 +1049,11 @@ typedef struct moo_t moo_t;
#define MOO_STATIC_ASSERT_EXPR(expr) ((void)MOO_SIZEOF(char[(expr)? 1: -1]))
/* =========================================================================
* QUOTING
* =========================================================================*/
#define MOO_BQ_(val) #val
#define MOO_BQ(val) MOO_BQ_(val)
#endif

View File

@ -1601,16 +1601,22 @@ int moo_importmod (
);
/*
* The moo_querymod() function finds a primitive function in modules
* The moo_querymodpf() function finds a primitive function in modules
* with a full primitive identifier.
*/
moo_pfbase_t* moo_querymod (
moo_pfbase_t* moo_querymodpf (
moo_t* moo,
const moo_ooch_t* pfid,
moo_oow_t pfidlen,
moo_mod_t** mod
);
moo_pvbase_t* moo_querymodpv (
moo_t* moo,
const moo_ooch_t* pvid,
moo_oow_t pvidlen,
moo_mod_t** mod
);
/* ========================================================================= */
/* pf-basic.c */

View File

@ -658,7 +658,7 @@ moo_mod_data_t* moo_openmod (moo_t* moo, const moo_ooch_t* name, moo_oow_t namel
MOO_DEBUG2 (moo, "Opened a module [%js] - %p\n", mdp->mod.name, mdp->handle);
/* the module loader must ensure to set a proper query handler */
MOO_ASSERT (moo, mdp->mod.query != MOO_NULL);
MOO_ASSERT (moo, mdp->mod.querypf != MOO_NULL);
return mdp;
}
@ -728,7 +728,7 @@ int moo_importmod (moo_t* moo, moo_oop_class_t _class, const moo_ooch_t* name, m
done:
/* close the module opened above.
* [NOTE] if the import callback calls the moo_querymod(), the returned
* [NOTE] if the import callback calls the moo_querymodpf(), the returned
* function pointers will get all invalidated here. so never do
* anything like that */
moo_closemod (moo, mdp);
@ -738,9 +738,9 @@ done2:
return r;
}
moo_pfbase_t* moo_querymod (moo_t* moo, const moo_ooch_t* pfid, moo_oow_t pfidlen, moo_mod_t** mod)
static void* query_mod (moo_t* moo, const moo_ooch_t* pid, moo_oow_t pidlen, moo_mod_t** mod, int pv)
{
/* primitive function identifier
/* primitive function/value identifier
* modname.funcname
* modname.modname2.funcname
*/
@ -749,27 +749,33 @@ moo_pfbase_t* moo_querymod (moo_t* moo, const moo_ooch_t* pfid, moo_oow_t pfidle
const moo_ooch_t* sep;
moo_oow_t mod_name_len;
moo_pfbase_t* pfbase;
void* base;
sep = moo_rfind_oochar(pfid, pfidlen, '.');
static const moo_bch_t* tags[] =
{
"function",
"value"
};
sep = moo_rfind_oochar(pid, pidlen, '.');
if (!sep)
{
/* i'm writing a conservative code here. the compiler should
* guarantee that a period is included in an primitive function identifer.
* what if the compiler is broken? imagine a buggy compiler rewritten
* in moo itself? */
MOO_DEBUG2 (moo, "Internal error - no period in a primitive function identifier [%.*js] - buggy compiler?\n", pfidlen, pfid);
moo_seterrbfmt (moo, MOO_EINTERN, "no period in a primitive function identifier [%.*js]", pfidlen, pfid);
MOO_DEBUG3 (moo, "Internal error - no period in a primitive %hs identifier [%.*js] - buggy compiler?\n", tags[pv], pidlen, pid);
moo_seterrbfmt (moo, MOO_EINTERN, "no period in a primitive %hs identifier [%.*js]", tags[pv], pidlen, pid);
return MOO_NULL;
}
mod_name_len = sep - pfid;
mod_name_len = sep - pid;
/* 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);
pair = moo_rbt_search(&moo->modtab, pid, mod_name_len);
if (pair)
{
mdp = (moo_mod_data_t*)MOO_RBT_VPTR(pair);
@ -778,23 +784,35 @@ moo_pfbase_t* moo_querymod (moo_t* moo, const moo_ooch_t* pfid, moo_oow_t pfidle
else
{
/* open a module using the part before the last period */
mdp = moo_openmod(moo, pfid, mod_name_len, 0);
mdp = moo_openmod(moo, pid, mod_name_len, 0);
if (!mdp) return MOO_NULL;
}
if ((pfbase = mdp->mod.query(moo, &mdp->mod, sep + 1, pfidlen - mod_name_len - 1)) == MOO_NULL)
base = pv? mdp->mod.querypv(moo, &mdp->mod, sep + 1, pidlen - mod_name_len - 1):
mdp->mod.querypf(moo, &mdp->mod, sep + 1, pidlen - mod_name_len - 1);
if (!base)
{
/* the primitive function is not found. but keep the module open even if it's opened above */
MOO_DEBUG3 (moo, "Cannot find a primitive function [%.*js] in a module [%js]\n", pfidlen - mod_name_len - 1, sep + 1, mdp->mod.name);
moo_seterrbfmt (moo, MOO_ENOENT, "unable to find a primitive function [%.*js] in a module [%js]", pfidlen - mod_name_len - 1, sep + 1, mdp->mod.name);
MOO_DEBUG4 (moo, "Cannot find a primitive %hs [%.*js] in a module [%js]\n", tags[pv], pidlen - mod_name_len - 1, sep + 1, mdp->mod.name);
moo_seterrbfmt (moo, MOO_ENOENT, "unable to find a primitive %hs [%.*js] in a module [%js]", tags[pv], pidlen - mod_name_len - 1, sep + 1, mdp->mod.name);
return MOO_NULL;
}
if (mod) *mod = &mdp->mod;
MOO_DEBUG4 (moo, "Found a primitive function [%.*js] in a module [%js] - %p\n",
pfidlen - mod_name_len - 1, sep + 1, mdp->mod.name, pfbase);
return pfbase;
MOO_DEBUG5 (moo, "Found a primitive %hs [%.*js] in a module [%js] - %p\n",
tags[pv], pidlen - mod_name_len - 1, sep + 1, mdp->mod.name, base);
return base;
}
moo_pfbase_t* moo_querymodpf (moo_t* moo, const moo_ooch_t* pfid, moo_oow_t pfidlen, moo_mod_t** mod)
{
return (moo_pfbase_t*)query_mod(moo, pfid, pfidlen, mod, 0);
}
moo_pvbase_t* moo_querymodpv (moo_t* moo, const moo_ooch_t* pvid, moo_oow_t pvidlen, moo_mod_t** mod)
{
return (moo_pvbase_t*)query_mod(moo, pvid, pvidlen, mod, 1);
}
/* -------------------------------------------------------------------------- */
@ -965,6 +983,25 @@ moo_pfbase_t* moo_findpfbase (moo_t* moo, moo_pfinfo_t* pfinfo, moo_oow_t pfcoun
return MOO_NULL;
}
moo_pvbase_t* moo_findpvbase (moo_t* moo, moo_pvinfo_t* pvinfo, moo_oow_t pvcount, const moo_ooch_t* name, moo_oow_t namelen)
{
int n;
/* binary search */
moo_oow_t base, mid, lim;
for (base = 0, lim = pvcount; lim > 0; lim >>= 1)
{
mid = base + (lim >> 1);
n = moo_comp_oochars_bcstr(name, namelen, pvinfo[mid].name);
if (n == 0) return &pvinfo[mid].base;
if (n > 0) { base = mid + 1; lim--; }
}
moo_seterrnum (moo, MOO_ENOENT);
return MOO_NULL;
}
/* -------------------------------------------------------------------------- */
int moo_setclasstrsize (moo_t* moo, moo_oop_class_t _class, moo_oow_t size, moo_trgc_t trgc)

View File

@ -1332,21 +1332,27 @@ struct moo_pfinfo_t
moo_pfbase_t base;
};
/*
typedef struct moo_pvbase_t moo_pvbase_t
enum moo_pvtype_t
{
void* ptr;
moo_oow_t len;
moo_oow_t type;
MOO_PV_INT,
MOO_PV_STR,
MOO_PV_SYM
};
typedef enum moo_pvtype_t moo_pvtype_t;
struct moo_pvbase_t
{
moo_pvtype_t type;
const void* vstr;
};
typedef struct moo_pvbase_t moo_pvbase_t;
typedef struct moo_pvinfo_t moo_pvinfo_t;
struct moo_pvinfo_t
{
moo_ooch_t name[32];
const moo_bch_t* name;
moo_pvbase_t base;
};
*/
/* receiver check failure leads to hard failure.
* RATIONAL: the primitive handler should be used by relevant classes and
@ -1386,7 +1392,14 @@ typedef int (*moo_mod_import_t) (
moo_oop_class_t _class
);
typedef moo_pfbase_t* (*moo_mod_query_t) (
typedef moo_pfbase_t* (*moo_mod_querypf_t) (
moo_t* moo,
moo_mod_t* mod,
const moo_ooch_t* name,
moo_oow_t namelen
);
typedef moo_pfbase_t* (*moo_mod_querypv_t) (
moo_t* moo,
moo_mod_t* mod,
const moo_ooch_t* name,
@ -1411,11 +1424,12 @@ struct moo_mod_t
unsigned 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;
moo_mod_import_t import;
moo_mod_querypf_t querypf;
moo_mod_querypv_t querypv;
moo_mod_unload_t unload;
moo_mod_gc_t gc;
void* ctx;
};
struct moo_mod_data_t
@ -2430,6 +2444,14 @@ MOO_EXPORT moo_pfbase_t* moo_findpfbase (
moo_oow_t namelen
);
MOO_EXPORT moo_pvbase_t* moo_findpvbase (
moo_t* moo,
moo_pvinfo_t* pvinfo,
moo_oow_t pvcount,
const moo_ooch_t* name,
moo_oow_t namelen
);
/* =========================================================================
* STRING ENCODING CONVERSION
* ========================================================================= */

View File

@ -267,11 +267,11 @@ static moo_pfinfo_t pfinfos[] =
static int import (moo_t* moo, moo_mod_t* mod, moo_oop_class_t _class)
{
if (moo_setclasstrsize (moo, _class, MOO_SIZEOF(console_t), MOO_NULL) <= -1) return -1;
if (moo_setclasstrsize(moo, _class, MOO_SIZEOF(console_t), MOO_NULL) <= -1) return -1;
return 0;
}
static moo_pfbase_t* query (moo_t* moo, moo_mod_t* mod, const moo_ooch_t* name, moo_oow_t namelen)
static moo_pfbase_t* querypf (moo_t* moo, moo_mod_t* mod, const moo_ooch_t* name, moo_oow_t namelen)
{
return moo_findpfbase(moo, pfinfos, MOO_COUNTOF(pfinfos), name, namelen);
}
@ -285,7 +285,8 @@ static void unload (moo_t* moo, moo_mod_t* mod)
int moo_mod_con (moo_t* moo, moo_mod_t* mod)
{
mod->import = import;
mod->query = query;
mod->querypf = querypf;
mod->querypv = MOO_NULL;
mod->unload = unload;
mod->ctx = MOO_NULL;
return 0;

View File

@ -1212,7 +1212,7 @@ static int import (moo_t* moo, moo_mod_t* mod, moo_oop_class_t _class)
return 0;
}
static moo_pfbase_t* query (moo_t* moo, moo_mod_t* mod, const moo_ooch_t* name, moo_oow_t namelen)
static moo_pfbase_t* querypf (moo_t* moo, moo_mod_t* mod, const moo_ooch_t* name, moo_oow_t namelen)
{
return moo_findpfbase (moo, pfinfos, MOO_COUNTOF(pfinfos), name, namelen);
}
@ -1226,7 +1226,8 @@ static void unload (moo_t* moo, moo_mod_t* mod)
int moo_mod_ffi (moo_t* moo, moo_mod_t* mod)
{
mod->import = import;
mod->query = query;
mod->querypf = querypf;
mod->querypv = MOO_NULL;
mod->unload = unload;
mod->ctx = MOO_NULL;
return 0;

View File

@ -122,6 +122,13 @@ static moo_pfinfo_t pfinfos[] =
{ I, "open:flags:mode:", 0, { pf_open_file, 3, 3 } },
};
static moo_pvinfo_t pvinfos[] =
{
{ "O_NONBLOCK", { MOO_PV_INT, MOO_BQ(O_NONBLOCK) } },
{ "O_RDONLY", { MOO_PV_INT, MOO_BQ(O_RDONLY) } },
{ "O_RDWR", { MOO_PV_INT, MOO_BQ(O_RDWR) } },
{ "O_WRONLY", { MOO_PV_INT, MOO_BQ(O_WRONLY) } }
};
/* ------------------------------------------------------------------------ */
static int import (moo_t* moo, moo_mod_t* mod, moo_oop_class_t _class)
@ -130,20 +137,25 @@ static int import (moo_t* moo, moo_mod_t* mod, moo_oop_class_t _class)
return 0;
}
static moo_pfbase_t* query (moo_t* moo, moo_mod_t* mod, const moo_ooch_t* name, moo_oow_t namelen)
static moo_pfbase_t* querypf (moo_t* moo, moo_mod_t* mod, const moo_ooch_t* name, moo_oow_t namelen)
{
return moo_findpfbase(moo, pfinfos, MOO_COUNTOF(pfinfos), name, namelen);
}
static moo_pvbase_t* querypv (moo_t* moo, moo_mod_t* mod, const moo_ooch_t* name, moo_oow_t namelen)
{
return moo_findpvbase(moo, pvinfos, MOO_COUNTOF(pvinfos), name, namelen);
}
static void 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..*/
}
int moo_mod_io_file (moo_t* moo, moo_mod_t* mod)
{
mod->import = import;
mod->query = query;
mod->querypf = querypf;
mod->querypv = querypv;
mod->unload = unload;
mod->ctx = MOO_NULL;
return 0;

View File

@ -234,7 +234,7 @@ static int import (moo_t* moo, moo_mod_t* mod, moo_oop_class_t _class)
return 0;
}
static moo_pfbase_t* query (moo_t* moo, moo_mod_t* mod, const moo_ooch_t* name, moo_oow_t namelen)
static moo_pfbase_t* querypf (moo_t* moo, moo_mod_t* mod, const moo_ooch_t* name, moo_oow_t namelen)
{
return moo_findpfbase(moo, pfinfos, MOO_COUNTOF(pfinfos), name, namelen);
}
@ -248,7 +248,8 @@ static void unload (moo_t* moo, moo_mod_t* mod)
int moo_mod_io (moo_t* moo, moo_mod_t* mod)
{
mod->import = import;
mod->query = query;
mod->querypf = querypf;
mod->querypv = MOO_NULL;
mod->unload = unload;
return 0;
}

View File

@ -519,7 +519,7 @@ static int import (moo_t* moo, moo_mod_t* mod, moo_oop_class_t _class)
return 0;
}
static moo_pfbase_t* query (moo_t* moo, moo_mod_t* mod, const moo_ooch_t* name, moo_oow_t namelen)
static moo_pfbase_t* querypf (moo_t* moo, moo_mod_t* mod, const moo_ooch_t* name, moo_oow_t namelen)
{
return moo_findpfbase (moo, pfinfos, MOO_COUNTOF(pfinfos), name, namelen);
}
@ -532,7 +532,8 @@ static void unload (moo_t* moo, moo_mod_t* mod)
int moo_mod_sck_addr (moo_t* moo, moo_mod_t* mod)
{
mod->import = import;
mod->query = query;
mod->querypf = querypf;
mod->querypv = MOO_NULL;
mod->unload = unload;
mod->ctx = MOO_NULL;
return 0;

View File

@ -597,7 +597,7 @@ static int import (moo_t* moo, moo_mod_t* mod, moo_oop_class_t _class)
return 0;
}
static moo_pfbase_t* query (moo_t* moo, moo_mod_t* mod, const moo_ooch_t* name, moo_oow_t namelen)
static moo_pfbase_t* querypf (moo_t* moo, moo_mod_t* mod, const moo_ooch_t* name, moo_oow_t namelen)
{
return moo_findpfbase(moo, pfinfos, MOO_COUNTOF(pfinfos), name, namelen);
}
@ -650,7 +650,8 @@ int moo_mod_sck (moo_t* moo, moo_mod_t* mod)
*/
mod->import = import;
mod->query = query;
mod->querypf = querypf;
mod->querypv = MOO_NULL;
mod->unload = unload;
return 0;
}

View File

@ -225,7 +225,7 @@ static int import (moo_t* moo, moo_mod_t* mod, moo_oop_class_t _class)
return 0;
}
static moo_pfbase_t* query (moo_t* moo, moo_mod_t* mod, const moo_ooch_t* name, moo_oow_t namelen)
static moo_pfbase_t* querypf (moo_t* moo, moo_mod_t* mod, const moo_ooch_t* name, moo_oow_t namelen)
{
return moo_findpfbase(moo, pfinfos, MOO_COUNTOF(pfinfos), name, namelen);
}
@ -249,7 +249,8 @@ static void unload (moo_t* moo, moo_mod_t* mod)
int moo_mod_stdio (moo_t* moo, moo_mod_t* mod)
{
mod->import = import;
mod->query = query;
mod->querypf = querypf;
mod->querypv = MOO_NULL;
mod->unload = unload;
mod->ctx = MOO_NULL;
return 0;

View File

@ -818,9 +818,9 @@ static int x11_import (moo_t* moo, moo_mod_t* mod, moo_oop_class_t _class)
return 0;
}
static moo_pfbase_t* x11_query (moo_t* moo, moo_mod_t* mod, const moo_ooch_t* name, moo_oow_t namelen)
static moo_pfbase_t* x11_querypf (moo_t* moo, moo_mod_t* mod, const moo_ooch_t* name, moo_oow_t namelen)
{
return moo_findpfbase (moo, x11_pfinfo, MOO_COUNTOF(x11_pfinfo), name, namelen);
return moo_findpfbase(moo, x11_pfinfo, MOO_COUNTOF(x11_pfinfo), name, namelen);
}
static void x11_unload (moo_t* moo, moo_mod_t* mod)
@ -869,7 +869,8 @@ int moo_mod_x11 (moo_t* moo, moo_mod_t* mod)
}
mod->import = x11_import;
mod->query = x11_query;
mod->querypf = x11_querypf;
mod->querypv = MOO_NULL;
mod->unload = x11_unload;
return 0;