Skip to content

Commit

Permalink
feat(expr): support user-defined type
Browse files Browse the repository at this point in the history
  • Loading branch information
Water-Melon committed Mar 18, 2024
1 parent 0139fe5 commit 1719a4a
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 43 deletions.
4 changes: 2 additions & 2 deletions docs/Melon Developer Guide.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3237,8 +3237,8 @@ Their definitions can be found in melon/include/mln_types.h.
Uninitialize and release a class instance. `...` is the rest arguments to be passed to destructor.

49) Expression
a) mln_expr_val_t *mln_expr_val_new(mln_expr_typ_t type, void *data);
Create an expression value object.
a) mln_expr_val_t *mln_expr_val_new(mln_expr_typ_t type, void *data, mln_expr_udata_free free);
Create an expression value object. `free` is used to free user-data `data` if `type` is `mln_expr_type_udata` or `mln_expr_type_string`.

b) void mln_expr_val_free(mln_expr_val_t *ev);
Free an expression value object.
Expand Down
40 changes: 26 additions & 14 deletions docs/book/cn/expr.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,24 +42,29 @@ concat("abc", concat(bcd, "efg")) --这个例子展示了函数嵌套调用
#### mln_expr_val_new

```c
mln_expr_val_t *mln_expr_val_new(mln_expr_typ_t type, void *data);
mln_expr_val_t *mln_expr_val_new(mln_expr_typ_t type, void *data, mln_expr_udata_free free);

typedef void (*mln_expr_udata_free)(void *);

typedef enum {
mln_expr_type_null = 0,
mln_expr_type_bool,
mln_expr_type_int,
mln_expr_type_real,
mln_expr_type_string,
mln_expr_type_udata,
} mln_expr_typ_t;

typedef struct {
mln_expr_typ_t type;
mln_expr_typ_t type;
union {
mln_u8_t b;
mln_s64_t i;
double r;
mln_string_t *s;
mln_u8_t b;
mln_s64_t i;
double r;
mln_string_t *s;
void *u;
} data;
mln_expr_udata_free free;
} mln_expr_val_t;
```
Expand All @@ -69,6 +74,7 @@ typedef struct {
- `mln_s64_t *`
- `double *`
- `mln_string_t *` 字符串会在函数内使用函数`mln_string_ref`引用该字符串。
- `void *` 用户自定义数据。可以使用第三个参数`free`来释放这个用户数据。
返回值:
Expand All @@ -83,7 +89,7 @@ typedef struct {
void mln_expr_val_free(mln_expr_val_t *ev);
```

描述:释放一个表达式值对象。
描述:释放一个表达式值对象。如果值是`string`类型,同时`free`回调也被设置,那么将使用`free`对字符串进行释放,否则使用`mln_string_free`释放字符串。

返回值:无

Expand All @@ -95,7 +101,7 @@ void mln_expr_val_free(mln_expr_val_t *ev);
void mln_expr_val_dup(mln_expr_val_t *dest, mln_expr_val_t *src);
```
描述:拷贝一个表达式值对象。将`src`的内容拷贝到`dest`中。如果是字符串类型,则会使用函数`mln_string_ref`引用字符串。
描述:拷贝一个表达式值对象。将`src`的内容拷贝到`dest`中。如果是字符串类型,则会使用函数`mln_string_ref`引用字符串。如果是`udata`类型,则直接复制数据指针,并将`src`的`free`置`NULL`,保证`src`释放时,用户自定义数据不会被释放。
返回值:无
Expand Down Expand Up @@ -127,12 +133,18 @@ typedef mln_expr_val_t *(*mln_expr_cb_t)(mln_string_t *name, int is_func, mln_ar

static mln_expr_val_t *var_expr_handler(mln_string_t *name, int is_func, mln_array_t *args, void *data)
{
mln_string_t *s;
mln_expr_val_t *ret;

printf("%p %p %p\n", name, args, data);
if (is_func)
mln_log(none, "%S %d %U %X\n", name, is_func, args->nelts, data);
else
mln_log(none, "%S %d %X\n", name, is_func, data);
return mln_expr_val_new(mln_expr_type_string, name);
if ((s = mln_string_dup(name)) == NULL) return NULL;
ret = mln_expr_val_new(mln_expr_type_string, s, NULL);
mln_string_free(s);
return ret;
}

static mln_expr_val_t *func_expr_handler(mln_string_t *name, int is_func, mln_array_t *args, void *data)
Expand All @@ -142,7 +154,7 @@ static mln_expr_val_t *func_expr_handler(mln_string_t *name, int is_func, mln_ar
mln_string_t *s1 = NULL, *s2, *s3;

if (!is_func)
return mln_expr_val_new(mln_expr_type_string, name);
return mln_expr_val_new(mln_expr_type_string, name, NULL);

for (i = 0, v = p = mln_array_elts(args); i < mln_array_nelts(args); v = p + (++i)) {
if (s1 == NULL) {
Expand All @@ -155,7 +167,7 @@ static mln_expr_val_t *func_expr_handler(mln_string_t *name, int is_func, mln_ar
s1 = s3;
}

v = mln_expr_val_new(mln_expr_type_string, s1);
v = mln_expr_val_new(mln_expr_type_string, s1, NULL);
mln_string_free(s1);

return v;
Expand Down Expand Up @@ -191,9 +203,9 @@ int main(void)
执行结果:
```
0xaaaae8d9a210 (nil) (nil)
0x4b1ac98 (nil) (nil)
aaa 0 0
03/18/2024 03:34:58 UTC DEBUG: a.c:main:53: PID:2293415 4 aaa
03/18/2024 03:34:58 UTC DEBUG: a.c:main:61: PID:2293415 4 abcaaabcdeee
03/18/2024 06:18:10 UTC DEBUG: a.c:main:59: PID:2303523 4 aaa
03/18/2024 06:18:10 UTC DEBUG: a.c:main:67: PID:2303523 4 abcaaabcdeee
```
40 changes: 26 additions & 14 deletions docs/book/en/expr.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,24 +42,29 @@ concat("abc", concat(bcd, "efg")) -- This example demonstrates nested function c
#### mln_expr_val_new

```c
mln_expr_val_t *mln_expr_val_new(mln_expr_typ_t type, void *data);
mln_expr_val_t *mln_expr_val_new(mln_expr_typ_t type, void *data, mln_expr_udata_free free);

typedef void (*mln_expr_udata_free)(void *);

typedef enum {
mln_expr_type_null = 0,
mln_expr_type_bool,
mln_expr_type_int,
mln_expr_type_real,
mln_expr_type_string,
mln_expr_type_udata,
} mln_expr_typ_t;

typedef struct {
mln_expr_typ_t type;
mln_expr_typ_t type;
union {
mln_u8_t b;
mln_s64_t i;
double r;
mln_string_t *s;
mln_u8_t b;
mln_s64_t i;
double r;
mln_string_t *s;
void *u;
} data;
mln_expr_udata_free free;
} mln_expr_val_t;
```
Expand All @@ -69,6 +74,7 @@ Description: Create an expression value object. `mln_expr_typ_t` is the type of
- `mln_s64_t *`
- `double *`
- `mln_string_t *` Strings will be referenced using the `mln_string_ref` within the function.
- `void *` User-defined data. It can be freed by the free function indicated by the third parameter of this function.
Return values:
Expand All @@ -83,7 +89,7 @@ Return values:
void mln_expr_val_free(mln_expr_val_t *ev);
```

Description: Free an expression value object.
Description: Free an expression value object. If the value is of type `string` and the `free` callback is also set, then the string will be freed using `free`; otherwise, `mln_string_free` will be used for freeing.

Return value: None

Expand All @@ -95,7 +101,7 @@ Return value: None
void mln_expr_val_dup(mln_expr_val_t *dest, mln_expr_val_t *src);
```
Description: duplicate an expression value object. Duplicate the content of `src` to `dest`. If the type is a string, the function `mln_string_ref` will be used to reference the string.
Description: duplicate an expression value object. Duplicate the content of `src` to `dest`. If the type is a string, the function `mln_string_ref` will be used to reference the string. If it is of type `udata`, simply copy the data pointer and set `src`'s `free` to `NULL`, ensuring that the user-defined data is not freed when `src` is released.
Return value: None
Expand Down Expand Up @@ -127,12 +133,18 @@ Return values:

static mln_expr_val_t *var_expr_handler(mln_string_t *name, int is_func, mln_array_t *args, void *data)
{
mln_string_t *s;
mln_expr_val_t *ret;

printf("%p %p %p\n", name, args, data);
if (is_func)
mln_log(none, "%S %d %U %X\n", name, is_func, args->nelts, data);
else
mln_log(none, "%S %d %X\n", name, is_func, data);
return mln_expr_val_new(mln_expr_type_string, name);
if ((s = mln_string_dup(name)) == NULL) return NULL;
ret = mln_expr_val_new(mln_expr_type_string, s, NULL);
mln_string_free(s);
return ret;
}

static mln_expr_val_t *func_expr_handler(mln_string_t *name, int is_func, mln_array_t *args, void *data)
Expand All @@ -142,7 +154,7 @@ static mln_expr_val_t *func_expr_handler(mln_string_t *name, int is_func, mln_ar
mln_string_t *s1 = NULL, *s2, *s3;

if (!is_func)
return mln_expr_val_new(mln_expr_type_string, name);
return mln_expr_val_new(mln_expr_type_string, name, NULL);

for (i = 0, v = p = mln_array_elts(args); i < mln_array_nelts(args); v = p + (++i)) {
if (s1 == NULL) {
Expand All @@ -155,7 +167,7 @@ static mln_expr_val_t *func_expr_handler(mln_string_t *name, int is_func, mln_ar
s1 = s3;
}

v = mln_expr_val_new(mln_expr_type_string, s1);
v = mln_expr_val_new(mln_expr_type_string, s1, NULL);
mln_string_free(s1);

return v;
Expand Down Expand Up @@ -191,9 +203,9 @@ int main(void)
Execution result:
```
0xaaaae8d9a210 (nil) (nil)
0x4b1ac98 (nil) (nil)
aaa 0 0
03/18/2024 03:34:58 UTC DEBUG: a.c:main:53: PID:2293415 4 aaa
03/18/2024 03:34:58 UTC DEBUG: a.c:main:61: PID:2293415 4 abcaaabcdeee
03/18/2024 06:18:10 UTC DEBUG: a.c:main:59: PID:2303523 4 aaa
03/18/2024 06:18:10 UTC DEBUG: a.c:main:67: PID:2303523 4 abcaaabcdeee
```
17 changes: 11 additions & 6 deletions include/mln_expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,27 @@

#define MLN_EXPR_DEFAULT_ARGS 8

typedef void (*mln_expr_udata_free)(void *);

typedef enum {
mln_expr_type_null = 0,
mln_expr_type_bool,
mln_expr_type_int,
mln_expr_type_real,
mln_expr_type_string,
mln_expr_type_udata,
} mln_expr_typ_t;

typedef struct {
mln_expr_typ_t type;
mln_expr_typ_t type;
union {
mln_u8_t b;
mln_s64_t i;
double r;
mln_string_t *s;
mln_u8_t b;
mln_s64_t i;
double r;
mln_string_t *s;
void *u;
} data;
mln_expr_udata_free free;
} mln_expr_val_t;

typedef mln_expr_val_t *(*mln_expr_cb_t)(mln_string_t *name, \
Expand All @@ -39,7 +44,7 @@ typedef mln_expr_val_t *(*mln_expr_cb_t)(mln_string_t *name, \
void *data);

extern mln_expr_val_t *mln_expr_run(mln_string_t *exp, mln_expr_cb_t cb, void *data);
extern mln_expr_val_t *mln_expr_val_new(mln_expr_typ_t type, void *data);
extern mln_expr_val_t *mln_expr_val_new(mln_expr_typ_t type, void *data, mln_expr_udata_free free);
extern void mln_expr_val_free(mln_expr_val_t *ev);
extern void mln_expr_val_dup(mln_expr_val_t *dest, mln_expr_val_t *src);
#endif
39 changes: 32 additions & 7 deletions src/mln_expr.c
Original file line number Diff line number Diff line change
Expand Up @@ -158,30 +158,40 @@ MLN_FUNC(static inline, int, mln_expr_val_init, (mln_expr_val_t *v, mln_expr_str
default:
return -1;
}
v->free = NULL;

return 0;
})

MLN_FUNC(, mln_expr_val_t *, mln_expr_val_new, (mln_expr_typ_t type, void *data), (type, data), {
MLN_FUNC(, mln_expr_val_t *, mln_expr_val_new, (mln_expr_typ_t type, void *data, mln_expr_udata_free free), (type, data, free), {
mln_expr_val_t *ev;

if ((ev = (mln_expr_val_t *)malloc(sizeof(mln_expr_val_t))) == NULL) return NULL;

ev->type = type;
switch (type) {
case mln_expr_type_null:
ev->free = NULL;
break;
case mln_expr_type_bool:
ev->data.b = *((mln_u8ptr_t)data);
ev->free = NULL;
break;
case mln_expr_type_int:
ev->data.i = *((mln_s64_t *)data);
ev->free = NULL;
break;
case mln_expr_type_real:
ev->data.r = *((double *)data);
ev->free = NULL;
break;
default: /* mln_expr_type_string */
case mln_expr_type_string:
ev->data.s = mln_string_ref((mln_string_t *)data);
ev->free = free;
break;
default: /* mln_expr_type_udata */
ev->data.u = data;
ev->free = free;
break;
}
return ev;
Expand All @@ -190,14 +200,23 @@ MLN_FUNC(, mln_expr_val_t *, mln_expr_val_new, (mln_expr_typ_t type, void *data)
MLN_FUNC_VOID(, void, mln_expr_val_free, (mln_expr_val_t *ev), (ev), {
if (ev == NULL) return;

if (ev->type == mln_expr_type_string)
mln_string_free(ev->data.s);
if (ev->type == mln_expr_type_string) {
if (ev->free != NULL) ev->free(ev->data.s);
else mln_string_free(ev->data.s);
} else if (ev->type == mln_expr_type_udata) {
if (ev->free != NULL) ev->free(ev->data.u);
}

free(ev);
})

MLN_FUNC_VOID(static, void, mln_expr_val_destroy, (mln_expr_val_t *ev), (ev), {
if (ev->type == mln_expr_type_string)
mln_string_free(ev->data.s);
if (ev->type == mln_expr_type_string) {
if (ev->free != NULL) ev->free(ev->data.s);
else mln_string_free(ev->data.s);
} else if (ev->type == mln_expr_type_udata) {
if (ev->free != NULL) ev->free(ev->data.u);
}
})

MLN_FUNC_VOID(, void, mln_expr_val_dup, (mln_expr_val_t *dest, mln_expr_val_t *src), (dest, src), {
Expand All @@ -216,8 +235,14 @@ MLN_FUNC_VOID(, void, mln_expr_val_dup, (mln_expr_val_t *dest, mln_expr_val_t *s
case mln_expr_type_real:
dest->data.r = src->data.r;
break;
default: /* mln_expr_type_string */
case mln_expr_type_string:
dest->data.s = mln_string_ref(src->data.s);
dest->free = src->free;
break;
default: /* mln_expr_type_udata */
dest->data.u = src->data.u;
dest->free = src->free;
src->free = NULL;
break;
}
})
Expand Down

0 comments on commit 1719a4a

Please sign in to comment.