Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# v1.10.1-alpha0
# v1.10.1-alpha1

* Improved `dict` export _(cosmetic)_, pr #462.
* Added alternative `wse(f(..))` using `f(..)!` syntax, issue #463, pr #464.

# v1.10.0

Expand Down
2 changes: 1 addition & 1 deletion grammar/grammar.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ class LangDef(Grammar):

thing = Sequence(x_thing, List(Sequence(name, ':', Optional(THIS))), '}')
array = Sequence(x_array, List(THIS), ']')
function = Sequence(x_function, List(THIS), ')')
function = Sequence(x_function, List(THIS), Regex(r'\)\!?'))
instance = Repeat(thing, mi=1, ma=1) # will be exported as `cleri_dup_t`
enum_ = Sequence(x_thing, Choice(name, closure), '}')

Expand Down
2 changes: 1 addition & 1 deletion inc/langdef/langdef.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* should be used with the libcleri module.
*
* Source class: LangDef
* Created at: 2025-11-07 13:13:19
* Created at: 2026-10-08 11:10:33
*/
#ifndef CLERI_EXPORT_LANGDEF_H_
#define CLERI_EXPORT_LANGDEF_H_
Expand Down
2 changes: 1 addition & 1 deletion inc/ti/version.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
* "-rc0"
* ""
*/
#define TI_VERSION_PRE_RELEASE "-alpha0"
#define TI_VERSION_PRE_RELEASE "-alpha1"

#define TI_MAINTAINER \
"Jeroen van der Heijden <jeroen@cesbit.com>"
Expand Down
73 changes: 71 additions & 2 deletions itest/test_advanced.py
Original file line number Diff line number Diff line change
Expand Up @@ -1870,7 +1870,7 @@ async def test_closure_as_type_val(self, client):
set_type('Test', {
func: 'any'
});
.test = Test{func: || .x = 1};
.test = Test{func: |x| .x = x};
.test.id();
""")

Expand All @@ -1879,9 +1879,20 @@ async def test_closure_as_type_val(self, client):
r"closures with side effects require a change but none is "
r"created; use `wse\(...\)` to enforce a change;"):
await client.query(f"""//ti
thing({id}).func(); // requires a change
thing({id}).func(123); // requires a change
""")

res = await client.query(f"""//ti
wse(); thing({id}).func(123);
""")
self.assertEqual(res, 123)

# Alternative wse(..) syntax, issue #463, pr #464
res = await client.query(f"""//ti
thing({id}).func(123)!;
""")
self.assertEqual(res, 123)

async def test_future_or_wrap_ano_to_type(self, client):
await client.query(r"""//ti
set_type('A', {x: 'any'});
Expand Down Expand Up @@ -3065,6 +3076,64 @@ async def test_nested_arr_opt(self, client: Client):
self.assertEqual(res, {
'arr': [{'id': 2, 'name': 'Iris'}, {'id': 3, 'name': 'Cato'}]})

async def test_more_wse(self, client: Client):
q = client.query
await q("""//ti
// setters
new_procedure('set_x', |x| .x = x);
.set_x = |x| .x = x;
.x = 0;

// getters
.get_x = || .x;
.wse = || .x; // fake test;
""")

with self.assertRaisesRegex(
OperationError,
r"closures with side effects require a change but none is "
r"created; use `wse\(...\)` to enforce a change;"):
await client.query(f"""//ti
set_x(123);
""")

with self.assertRaisesRegex(
OperationError,
r"closures with side effects require a change but none is "
r"created; use `wse\(...\)` to enforce a change;"):
await client.query(f"""//ti
.set_x(42);
""")

res = await q("""//ti
.wse();
change_id();
""")
self.assertIs(res, None)

res = await q("""//ti
set_x(123)!;
""")
self.assertEqual(res, 123)

res = await q("""//ti
.set_x(42)!;
""")
self.assertEqual(res, 42)

res = await q("""//ti
.set_x(42)!.bit_count();
""")
self.assertEqual(res, 3)

with self.assertRaisesRegex(
SyntaxError,
r"error at line 1, position 11, unexpected character `!`, "
r"expecting: ; or end_of_statement"):
await client.query(f"""//ti
.set_x(42)!!;
""")


if __name__ == '__main__':
run_test(TestAdvanced())
4 changes: 2 additions & 2 deletions src/langdef/langdef.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* should be used with the libcleri module.
*
* Source class: LangDef
* Created at: 2025-11-07 13:13:19
* Created at: 2026-10-08 11:10:33
*/

#include <langdef/langdef.h>
Expand Down Expand Up @@ -107,7 +107,7 @@ cleri_grammar_t * compile_langdef(void)
3,
x_function,
cleri_list(CLERI_NONE, CLERI_THIS, cleri_token(CLERI_NONE, ","), 0, 0, 1),
cleri_token(CLERI_NONE, ")")
cleri_regex(CLERI_NONE, "^\\)\\!?")
);
cleri_t * instance = cleri_dup(CLERI_GID_INSTANCE, thing);
cleri_t * enum_ = cleri_sequence(
Expand Down
16 changes: 10 additions & 6 deletions src/ti/qbind.c
Original file line number Diff line number Diff line change
Expand Up @@ -1000,8 +1000,18 @@ static void qbind__function(
((FN__FLAG_ROOT|FN__FLAG_CHAIN) & flags & fmap->flags) &&
memcmp(fnname->str, fmap->name, n) == 0) ? fmap->flags : 0;

/* set build-in function if one found */
nd->data = fmflags ? fmap->fn : NULL;

/* update the value cache if no build-in function is found */
q->immutable_n += nd->data == NULL;

/* list (arguments) */
nd = nd->children->next->children->next;

/* set wse from `(..)!` syntax by checking node either `)` or `)!` */
fmflags |= (nd->next->len == 2) ? FN__FLAG_EV_T|FN__FLAG_EV_C : 0;

/* may set wse flag */
q->flags |= (
((FN__FLAG_EV_T|FN__FLAG_EV_C) & q->flags & fmflags) &&
Expand All @@ -1010,15 +1020,9 @@ static void qbind__function(
((~fmflags & FN__FLAG_XNSE) || (~q->flags & TI_QBIND_FLAG_NSE))
) << TI_QBIND_BIT_WSE;

/* update the value cache if no build-in function is found */
q->immutable_n += nd->data == NULL;

/* only used when no build-in function is found */
fnname->data = NULL;

/* list (arguments) */
nd = nd->children->next->children->next;

if (fmflags & FN__FLAG_NSE)
q->flags |= TI_QBIND_FLAG_NSE;

Expand Down
Loading