Skip to content

Commit

Permalink
Module type (#365)
Browse files Browse the repository at this point in the history
* work on module type

* No future with Id arguments

* Upd changelog

* Upd tests
  • Loading branch information
joente authored Mar 19, 2024
1 parent f0c2ef4 commit 1a32b54
Show file tree
Hide file tree
Showing 33 changed files with 428 additions and 79 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
# v1.5.2

* Restrict future arguments for `then()` or `else()` to objects without an Id.
* Module as type, no longer the workaround of exposing modules as futures.
* Added the `is_module()` function.
* Support ThingsDB code in exposed module functions.

# v1.5.1

* Added support for building on MacOS.
Expand Down
1 change: 1 addition & 0 deletions inc/doc.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
#define DOC_IS_INF DOC_SEE("collection-api/is/is_inf")
#define DOC_IS_INT DOC_SEE("collection-api/is/is_int")
#define DOC_IS_LIST DOC_SEE("collection-api/is/is_list")
#define DOC_IS_MODULE DOC_SEE("collection-api/is/is_module")
#define DOC_IS_MPDATA DOC_SEE("collection-api/is/is_mpdata")
#define DOC_IS_NAN DOC_SEE("collection-api/is/is_nan")
#define DOC_IS_NIL DOC_SEE("collection-api/is/is_nil")
Expand Down
9 changes: 5 additions & 4 deletions inc/ti/fn/fn.h
Original file line number Diff line number Diff line change
Expand Up @@ -649,12 +649,13 @@ static int fn_call_f_try_n(
cleri_node_t * nd,
ex_t * e)
{
ti_future_t * future = (ti_future_t *) query->rval;
ti_module_t * module = future->module;
ti_module_t * module = (ti_module_t *) query->rval;
ti_mod_expose_t * expose = ti_mod_expose_by_strn(module, name, n);

if (expose)
return ti_mod_expose_call(expose, query, nd, e);
return expose->closure
? ti_mod_closure_call(expose, query, nd, e)
: ti_mod_expose_call(expose, query, nd, e);

ex_set(e, EX_LOOKUP_ERROR,
"module `%s` has no function `%.*s`",
Expand Down Expand Up @@ -708,7 +709,7 @@ static int fn_call_try_n(
if (ti_val_is_wrap(query->rval))
return fn_call_w_try_n(name, n, query, nd, e);

if (ti_val_is_future(query->rval))
if (ti_val_is_module(query->rval))
return fn_call_f_try_n(name, n, query, nd, e);

if (ti_val_is_member(query->rval))
Expand Down
1 change: 1 addition & 0 deletions inc/ti/fn/fnclosure.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ static int do__f_closure_new(ti_query_t * query, cleri_node_t * nd, ex_t * e)
case TI_VAL_MEMBER:
case TI_VAL_MPDATA:
case TI_VAL_FUTURE:
case TI_VAL_MODULE:
ex_set(e, EX_TYPE_ERROR,
"cannot convert type `%s` to `"TI_VAL_CLOSURE_S"`",
ti_val_str(query->rval));
Expand Down
18 changes: 18 additions & 0 deletions inc/ti/fn/fnismodule.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#include <ti/fn/fn.h>

static int do__f_is_module(ti_query_t * query, cleri_node_t * nd, ex_t * e)
{
const int nargs = fn_get_nargs(nd);
_Bool is_module;

if (fn_nargs("is_module", DOC_IS_MODULE, 1, nargs, e) ||
ti_do_statement(query, nd->children, e))
return e->nr;

is_module = ti_val_is_module(query->rval);

ti_val_unsafe_drop(query->rval);
query->rval = (ti_val_t *) ti_vbool_get(is_module);

return 0;
}
1 change: 1 addition & 0 deletions inc/ti/fn/fnsearch.h
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ static int do__search_thing(
}
case TI_VAL_TEMPLATE:
case TI_VAL_FUTURE:
case TI_VAL_MODULE:
return 0;
}
assert(0);
Expand Down
3 changes: 2 additions & 1 deletion inc/ti/forloop.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ typedef int (*ti_forloop_t) (
cleri_node_t *,
ex_t *);

static const ti_forloop_t ti_forloop_callbacks[21] = {
static const ti_forloop_t ti_forloop_callbacks[22] = {
ti_forloop_no_iter, /* TI_VAL_NIL */
ti_forloop_no_iter, /* TI_VAL_INT */
ti_forloop_no_iter, /* TI_VAL_FLOAT */
Expand All @@ -60,6 +60,7 @@ static const ti_forloop_t ti_forloop_callbacks[21] = {
ti_forloop_no_iter, /* TI_VAL_MPDATA */
ti_forloop_no_iter, /* TI_VAL_CLOSURE */
ti_forloop_no_iter, /* TI_VAL_FUTURE */
ti_forloop_no_iter, /* TI_VAL_MODULE */
ti_forloop_no_iter, /* TI_VAL_TEMPLATE */
};

Expand Down
5 changes: 5 additions & 0 deletions inc/ti/mod/expose.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@

ti_mod_expose_t * ti_mod_expose_create(void);
void ti_mod_expose_destroy(ti_mod_expose_t * expose);
int ti_mod_closure_call(
ti_mod_expose_t * expose,
ti_query_t * query,
cleri_node_t * nd,
ex_t * e);
int ti_mod_expose_call(
ti_mod_expose_t * expose,
ti_query_t * query,
Expand Down
11 changes: 7 additions & 4 deletions inc/ti/mod/expose.t.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,17 @@
typedef struct ti_mod_expose_s ti_mod_expose_t;

#include <util/vec.h>
#include <ti/closure.t.h>

struct ti_mod_expose_s
{
uint8_t * deep; /* NULL or 0..127 */
uint8_t * deep; /* NULL or 0..127 */
_Bool * load; /* NULL or true/false */
char * doc; /* NULL or string */
vec_t * argmap; /* ti_item_t */
vec_t * defaults; /* ti_item_t */
char * doc; /* NULL or string */
vec_t * argmap; /* ti_item_t */
vec_t * defaults; /* ti_item_t */
ti_closure_t * closure; /* closure */
ti_raw_t * def; /* closure definition */
};

#endif /* TI_MOD_EXPOSE_T_H_ */
4 changes: 4 additions & 0 deletions inc/ti/module.t.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ typedef union
struct ti_module_s
{
uint32_t ref;
uint8_t tp;
uint8_t _pad0;
uint16_t _pad1;

int status; /* 0 = success, >0 = enum, <0 = uv error */
int flags;
uint16_t restarts; /* keep the number of times this module has been
Expand Down
1 change: 1 addition & 0 deletions inc/ti/thing.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ int ti_thing_get_by_raw_e(
ti_raw_t * r,
ex_t * e);
int ti_thing_gen_id(ti_thing_t * thing);
_Bool ti_thing_has_id(ti_thing_t * thing);
int ti_thing__to_client_pk(
ti_thing_t * thing,
ti_vp_t * vp,
Expand Down
1 change: 1 addition & 0 deletions inc/ti/val.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ int ti_val_convert_to_set(ti_val_t ** val, ex_t * e);
_Bool ti_val_as_bool(ti_val_t * val);
size_t ti_val_get_len(ti_val_t * val);
int ti_val_gen_ids(ti_val_t * val);
_Bool ti_val_has_ids(ti_val_t * val);
size_t ti_val_alloc_size(ti_val_t * val);
ti_val_t * ti_val_strv(ti_val_t * val);
int ti_val_copy(ti_val_t ** val, ti_thing_t * parent, void * key, uint8_t deep);
Expand Down
38 changes: 36 additions & 2 deletions inc/ti/val.inline.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <ti/future.h>
#include <ti/member.h>
#include <ti/member.inline.h>
#include <ti/module.t.h>
#include <ti/name.h>
#include <ti/nil.h>
#include <ti/nil.h>
Expand Down Expand Up @@ -117,7 +118,10 @@ static inline const char * val__future_type_str(ti_val_t * UNUSED(val))
{
return TI_VAL_FUTURE_S;
}

static inline const char * val__module_type_str(ti_val_t * UNUSED(val))
{
return TI_VAL_MODULE_S;
}
static inline int val__nil_to_client_pk(ti_val_t * UNUSED(v), ti_vp_t * vp, int UNUSED(d), int UNUSED(f))
{
return msgpack_pack_nil(&vp->pk);
Expand Down Expand Up @@ -183,6 +187,7 @@ static inline int val__closure_to_client_pk(ti_val_t * val, ti_vp_t * vp, int UN
return ti_closure_to_client_pk((ti_closure_t *) val, &vp->pk);
}
static inline int val__future_to_client_pk(ti_future_t * future, ti_vp_t * vp, int deep, int flags);
static inline int val__module_to_client_pk(ti_module_t * UNUSED(module), ti_vp_t * vp, int UNUSED(deep), int UNUSED(flags));
static inline int val__member_to_client_pk(ti_member_t * member, ti_vp_t * vp, int deep, int flags);
static inline int val__member_to_store_pk(ti_member_t * member, msgpack_packer * pk);
static inline int val__varr_to_client_pk(ti_varr_t * varr, ti_vp_t * vp, int deep, int flags);
Expand Down Expand Up @@ -229,6 +234,7 @@ static inline int val__set_to_arr(ti_val_t ** v, ti_varr_t * varr, ex_t * e)

static inline int val__member_to_arr(ti_val_t ** v, ti_varr_t * varr, ex_t * e);
static inline int val__future_to_arr(ti_val_t ** v, ti_varr_t * UNUSED(varr), ex_t * UNUSED(e));
static inline int val__module_to_arr(ti_val_t ** v, ti_varr_t * UNUSED(varr), ex_t * UNUSED(e));

static inline int val__closure_to_arr(ti_val_t ** v, ti_varr_t * UNUSED(varr), ex_t * e)
{
Expand All @@ -254,7 +260,7 @@ typedef struct
} ti_val_type_t;


static ti_val_type_t ti_val_type_props[21] = {
static ti_val_type_t ti_val_type_props[22] = {
/* TI_VAL_NIL */
{
.destroy = (ti_val_destroy_cb) free,
Expand Down Expand Up @@ -454,6 +460,15 @@ static ti_val_type_t ti_val_type_props[21] = {
.get_type_str = val__future_type_str,
.allowed_as_vtask_arg = false,
},
/* TI_VAL_MODULE */
{
.destroy = (ti_val_destroy_cb) ti_module_destroy,
.to_str = val__no_to_str,
.to_arr_cb = val__module_to_arr,
.to_client_pk = (ti_val_to_client_pk_cb) val__module_to_client_pk,
.get_type_str = val__module_type_str,
.allowed_as_vtask_arg = false,
},
/* TI_VAL_TEMPLATE */
{
.destroy = (ti_val_destroy_cb) ti_template_destroy,
Expand Down Expand Up @@ -751,6 +766,11 @@ static inline _Bool ti_val_is_future(ti_val_t * val)
return val->tp == TI_VAL_FUTURE;
}

static inline _Bool ti_val_is_module(ti_val_t * val)
{
return val->tp == TI_VAL_MODULE;
}

static inline _Bool ti_val_overflow_cast(double d)
{
return !(d >= -VAL__CAST_MAX && d < VAL__CAST_MAX);
Expand Down Expand Up @@ -1017,6 +1037,7 @@ static inline void ti_val_attach(
case TI_VAL_MEMBER:
case TI_VAL_CLOSURE:
case TI_VAL_FUTURE:
case TI_VAL_MODULE:
return;
case TI_VAL_ARR:
((ti_varr_t *) val)->parent = parent;
Expand Down Expand Up @@ -1088,6 +1109,7 @@ static inline int ti_val_make_assignable(
case TI_VAL_CLOSURE:
return ti_closure_unbound((ti_closure_t *) *val, e);
case TI_VAL_FUTURE:
case TI_VAL_MODULE:
ti_val_unsafe_drop(*val);
*val = (ti_val_t *) ti_nil_get();
return 0;
Expand Down Expand Up @@ -1119,6 +1141,11 @@ static inline int val__future_to_client_pk(ti_future_t * future, ti_vp_t * vp, i
: msgpack_pack_nil(&vp->pk);
}

static inline int val__module_to_client_pk(ti_module_t * UNUSED(module), ti_vp_t * vp, int UNUSED(deep), int UNUSED(flags))
{
return msgpack_pack_nil(&vp->pk);
}

static inline int val__member_to_client_pk(ti_member_t * member, ti_vp_t * vp, int deep, int flags)
{
return ti_val(member->val)->to_client_pk(member->val, vp, deep, flags);
Expand Down Expand Up @@ -1289,6 +1316,13 @@ static inline int val__future_to_arr(ti_val_t ** v, ti_varr_t * UNUSED(varr), ex
return 0;
}

static inline int val__module_to_arr(ti_val_t ** v, ti_varr_t * UNUSED(varr), ex_t * UNUSED(e))
{
ti_val_unsafe_drop(*v);
*v = (ti_val_t *) ti_nil_get();
return 0;
}

/*
* does not increment `*v` reference counter but the value might change to
* a (new) tuple pointer.
Expand Down
2 changes: 2 additions & 0 deletions inc/ti/val.t.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#define TI_VAL_DATETIME_S "datetime"
#define TI_VAL_TIMEVAL_S "timeval"
#define TI_VAL_FUTURE_S "future"
#define TI_VAL_MODULE_S "module"
#define TI_VAL_TASK_S "task"

#define TI_KIND_S_INSTANCE "." /* Internally, New typed thing */
Expand Down Expand Up @@ -66,6 +67,7 @@ typedef enum
TI_VAL_MPDATA, /* msgpack data */
TI_VAL_CLOSURE,
TI_VAL_FUTURE, /* future */
TI_VAL_MODULE, /* module */
TI_VAL_TEMPLATE, /* template to generate TI_VAL_STR
note that a template is never stored like a value,
rather it may build from either a query or a stored
Expand Down
4 changes: 2 additions & 2 deletions inc/ti/version.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

#define TI_VERSION_MAJOR 1
#define TI_VERSION_MINOR 5
#define TI_VERSION_PATCH 1
#define TI_VERSION_PATCH 2

/* The syntax version is used to test compatibility with functions
* using the `ti_nodes_check_syntax()` function */
Expand All @@ -25,7 +25,7 @@
* "-rc0"
* ""
*/
#define TI_VERSION_PRE_RELEASE ""
#define TI_VERSION_PRE_RELEASE "-alpha1"

#define TI_MAINTAINER \
"Jeroen van der Heijden <jeroen@cesbit.com>"
Expand Down
4 changes: 2 additions & 2 deletions itest/test_advanced.py
Original file line number Diff line number Diff line change
Expand Up @@ -1822,7 +1822,7 @@ async def test_future_to_type(self, client):
with self.assertRaisesRegex(
TypeError,
r'mismatch in type `A`; property `x` allows `any` type '
r"with the exception of the `future` type"):
r"with the exception of the `future` and `module` type"):
await client.query("""//ti
A{
x: future(||nil)
Expand Down Expand Up @@ -2504,7 +2504,7 @@ async def test_future_name(self, client):

with self.assertRaisesRegex(
LookupError,
r'module `async` has no function `id`'):
r'type `future` has no function `id`'):
await client.query(r"""//ti
user = add_user(); user.id();
""")
Expand Down
8 changes: 8 additions & 0 deletions itest/test_collection_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -2137,6 +2137,14 @@ async def test_is_future(self, client):
self.assertFalse(await client.query('is_future( 42 );'))
self.assertFalse(await client.query('is_future( nil );'))

async def test_is_module(self, client):
with self.assertRaisesRegex(
NumArgumentsError,
'function `is_module` takes 1 argument but 0 were given'):
await client.query('is_module();')

self.assertFalse(await client.query('is_module(future(nil));'))

async def test_is_inf(self, client):
with self.assertRaisesRegex(
NumArgumentsError,
Expand Down
11 changes: 11 additions & 0 deletions itest/test_future.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,5 +245,16 @@ async def test_future_arguments(self, client):
future(|a, b| a + b);
""")

async def test_no_ids(self, client):
with self.assertRaisesRegex(
OperationError,
'context does not allow arguments which are stored by Id'):
await client.query("""//ti
.t = t = {name: 'iris'};
future(|t| {
t.name = 'Iris';
});
""")

if __name__ == '__main__':
run_test(TestFuture())
Loading

0 comments on commit 1a32b54

Please sign in to comment.