From cda527fca0c2737496523a8ad6cedced04c056c8 Mon Sep 17 00:00:00 2001 From: Jeroen van der Heijden Date: Mon, 12 Feb 2024 11:24:04 +0100 Subject: [PATCH] Add Bit-wise Left and Right shift (#361) * implement bitshift * Added tests * Update changelog * Upd translate * Direct bind operation * manual inline --- CHANGELOG.md | 3 +- grammar/grammar.py | 34 ++++--- inc/langdef/langdef.h | 17 ++-- inc/ti/do.h | 11 ++ inc/ti/opr/and.h | 5 + inc/ti/opr/or.h | 5 + inc/ti/opr/sl.h | 35 +++++++ inc/ti/opr/sr.h | 35 +++++++ inc/ti/opr/xor.h | 5 + inc/ti/version.h | 2 +- itest/test_operators.py | 26 +++++ src/langdef/compat.c | 14 +-- src/langdef/langdef.c | 36 +++---- src/langdef/translate.c | 13 +-- src/ti/do.c | 217 ++++++++++++++++++++++++++++++++++++---- src/ti/fmt.c | 2 +- src/ti/ncache.c | 2 +- src/ti/opr.c | 18 ---- src/ti/qbind.c | 53 ++++++---- 19 files changed, 419 insertions(+), 114 deletions(-) create mode 100644 inc/ti/opr/sl.h create mode 100644 inc/ti/opr/sr.h diff --git a/CHANGELOG.md b/CHANGELOG.md index a376b4b4..d53008f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # v1.5.0 -* Comments can be placed anywhere that white-space is allowed. +* Comments can now be placed anywhere where white-space is allowed. * Comments are no longer stored within closures. This behavior was previously partially enforced, and now it is strictly followed. * Statements must be separated with semicolons. Syntax checking is now more strict. @@ -32,6 +32,7 @@ * Added set operators `<=`, `<`, `>=`, `>` for subset, proper subset, super-set and proper super-set checking. * Added range `<..>` support for UTF-8 type property definitions. * Added bit-wise NOT (`~`) operator. +* Added bit-wise Left (`<<`) and Right (`>>`) shifting operators. * Return `nil` instead of success error when a repeating task is successful. * Corrected a spelling mistake in error message for integer range values. * No longer allow a relation between a none-stored set and a none-stored value. diff --git a/grammar/grammar.py b/grammar/grammar.py index 84d23e10..f4824621 100644 --- a/grammar/grammar.py +++ b/grammar/grammar.py @@ -90,24 +90,26 @@ class LangDef(Grammar): opr0_mul_div_mod = Tokens('* / %') opr1_add_sub = Tokens('+ -') - opr2_bitwise_and = Tokens('&') - opr3_bitwise_xor = Tokens('^') - opr4_bitwise_or = Tokens('|') - opr5_compare = Tokens('< > == != <= >=') - opr6_cmp_and = Token('&&') - opr7_cmp_or = Token('||') - opr8_ternary = Sequence(x_ternary, THIS, ':') + opr2_bitwise_shift = Tokens('<< >>') + opr3_bitwise_and = Tokens('&') + opr4_bitwise_xor = Tokens('^') + opr5_bitwise_or = Tokens('|') + opr6_compare = Tokens('< > == != <= >=') + opr7_cmp_and = Token('&&') + opr8_cmp_or = Token('||') + opr9_ternary = Sequence(x_ternary, THIS, ':') operations = Sequence(THIS, Choice( # make sure `ternary`, `and` and `or` is on top so we can stop - # at the first match - opr8_ternary, - opr7_cmp_or, - opr6_cmp_and, - opr5_compare, - opr4_bitwise_or, - opr3_bitwise_xor, - opr2_bitwise_and, + # at the first match; The bitwise shift must be before compare. + opr9_ternary, + opr8_cmp_or, + opr7_cmp_and, + opr2_bitwise_shift, + opr6_compare, + opr5_bitwise_or, + opr4_bitwise_xor, + opr3_bitwise_and, opr1_add_sub, opr0_mul_div_mod, ), THIS) @@ -225,7 +227,7 @@ class LangDef(Grammar): if __name__ == '__main__': langdef = LangDef() - res = langdef.parse(r'''x = /./;''') + res = langdef.parse(r'''1 << 4;''') print(res.is_valid) res = langdef.parse(r'''/./;''') diff --git a/inc/langdef/langdef.h b/inc/langdef/langdef.h index b220dd29..a37197b4 100644 --- a/inc/langdef/langdef.h +++ b/inc/langdef/langdef.h @@ -5,7 +5,7 @@ * should be used with the libcleri module. * * Source class: LangDef - * Created at: 2024-02-05 10:13:48 + * Created at: 2024-02-11 20:55:25 */ #ifndef CLERI_EXPORT_LANGDEF_H_ #define CLERI_EXPORT_LANGDEF_H_ @@ -41,13 +41,14 @@ enum cleri_grammar_ids { CLERI_GID_OPERATIONS, CLERI_GID_OPR0_MUL_DIV_MOD, CLERI_GID_OPR1_ADD_SUB, - CLERI_GID_OPR2_BITWISE_AND, - CLERI_GID_OPR3_BITWISE_XOR, - CLERI_GID_OPR4_BITWISE_OR, - CLERI_GID_OPR5_COMPARE, - CLERI_GID_OPR6_CMP_AND, - CLERI_GID_OPR7_CMP_OR, - CLERI_GID_OPR8_TERNARY, + CLERI_GID_OPR2_BITWISE_SHIFT, + CLERI_GID_OPR3_BITWISE_AND, + CLERI_GID_OPR4_BITWISE_XOR, + CLERI_GID_OPR5_BITWISE_OR, + CLERI_GID_OPR6_COMPARE, + CLERI_GID_OPR7_CMP_AND, + CLERI_GID_OPR8_CMP_OR, + CLERI_GID_OPR9_TERNARY, CLERI_GID_PARENTHESIS, CLERI_GID_RETURN_STATEMENT, CLERI_GID_SLICE, diff --git a/inc/ti/do.h b/inc/ti/do.h index 73b2602a..60486ce4 100644 --- a/inc/ti/do.h +++ b/inc/ti/do.h @@ -13,6 +13,17 @@ typedef int (*ti_do_cb)(ti_query_t * query, cleri_node_t * nd, ex_t * e); int ti_do_expression(ti_query_t * query, cleri_node_t * nd, ex_t * e); int ti_do_operation(ti_query_t * query, cleri_node_t * nd, ex_t * e); +int ti_do_bit_sl(ti_query_t * query, cleri_node_t * nd, ex_t * e); +int ti_do_bit_sr(ti_query_t * query, cleri_node_t * nd, ex_t * e); +int ti_do_bit_and(ti_query_t * query, cleri_node_t * nd, ex_t * e); +int ti_do_bit_xor(ti_query_t * query, cleri_node_t * nd, ex_t * e); +int ti_do_bit_or(ti_query_t * query, cleri_node_t * nd, ex_t * e); +int ti_do_compare_eq(ti_query_t * query, cleri_node_t * nd, ex_t * e); +int ti_do_compare_ne(ti_query_t * query, cleri_node_t * nd, ex_t * e); +int ti_do_compare_lt(ti_query_t * query, cleri_node_t * nd, ex_t * e); +int ti_do_compare_le(ti_query_t * query, cleri_node_t * nd, ex_t * e); +int ti_do_compare_gt(ti_query_t * query, cleri_node_t * nd, ex_t * e); +int ti_do_compare_ge(ti_query_t * query, cleri_node_t * nd, ex_t * e); int ti_do_compare_and(ti_query_t * query, cleri_node_t * nd, ex_t * e); int ti_do_compare_or(ti_query_t * query, cleri_node_t * nd, ex_t * e); int ti_do_ternary(ti_query_t * query, cleri_node_t * nd, ex_t * e); diff --git a/inc/ti/opr/and.h b/inc/ti/opr/and.h index f5f39144..ed9f9481 100644 --- a/inc/ti/opr/and.h +++ b/inc/ti/opr/and.h @@ -1,3 +1,6 @@ +#ifndef TI_OPR_AND_H_ +#define TI_OPR_AND_H_ + #include static int opr__and(ti_val_t * a, ti_val_t ** b, ex_t * e, _Bool inplace) @@ -94,3 +97,5 @@ static int opr__and(ti_val_t * a, ti_val_t ** b, ex_t * e, _Bool inplace) ex_set_mem(e); return e->nr; } + +#endif /* TI_OPR_AND_H_ */ diff --git a/inc/ti/opr/or.h b/inc/ti/opr/or.h index ba94474a..23bb1b6d 100644 --- a/inc/ti/opr/or.h +++ b/inc/ti/opr/or.h @@ -1,3 +1,6 @@ +#ifndef TI_OPR_OR_H_ +#define TI_OPR_OR_H_ + #include static int opr__or(ti_val_t * a, ti_val_t ** b, ex_t * e, _Bool inplace) @@ -92,3 +95,5 @@ static int opr__or(ti_val_t * a, ti_val_t ** b, ex_t * e, _Bool inplace) ex_set_mem(e); return e->nr; } + +#endif /* TI_OPR_OR_H_ */ diff --git a/inc/ti/opr/sl.h b/inc/ti/opr/sl.h new file mode 100644 index 00000000..697a67b3 --- /dev/null +++ b/inc/ti/opr/sl.h @@ -0,0 +1,35 @@ +#include + +static int opr__sl(ti_val_t * a, ti_val_t ** b, ex_t * e) +{ + int64_t int_ = 0; /* set to 0 only to prevent warning */ + ti_opr_perm_t perm = TI_OPR_PERM(a, *b); + switch(perm) + { + default: + ex_set(e, EX_TYPE_ERROR, + "bitwise `<<` not supported between `%s` and `%s`", + ti_val_str(a), ti_val_str(*b)); + return e->nr; + + case OPR_INT_INT: + int_ = VINT(a) << VINT(*b); + break; + + case OPR_INT_BOOL: + int_ = VINT(a) << VBOOL(*b); + break; + + case OPR_BOOL_INT: + int_ = VBOOL(a) << VINT(*b); + break; + + case OPR_BOOL_BOOL: + int_ = VBOOL(a) << VBOOL(*b); + break; + + } + if (ti_val_make_int(b, int_)) + ex_set_mem(e); + return e->nr; +} diff --git a/inc/ti/opr/sr.h b/inc/ti/opr/sr.h new file mode 100644 index 00000000..efc379e4 --- /dev/null +++ b/inc/ti/opr/sr.h @@ -0,0 +1,35 @@ +#include + +static int opr__sr(ti_val_t * a, ti_val_t ** b, ex_t * e) +{ + int64_t int_ = 0; /* set to 0 only to prevent warning */ + ti_opr_perm_t perm = TI_OPR_PERM(a, *b); + switch(perm) + { + default: + ex_set(e, EX_TYPE_ERROR, + "bitwise `>>` not supported between `%s` and `%s`", + ti_val_str(a), ti_val_str(*b)); + return e->nr; + + case OPR_INT_INT: + int_ = VINT(a) >> VINT(*b); + break; + + case OPR_INT_BOOL: + int_ = VINT(a) >> VBOOL(*b); + break; + + case OPR_BOOL_INT: + int_ = VBOOL(a) >> VINT(*b); + break; + + case OPR_BOOL_BOOL: + int_ = VBOOL(a) >> VBOOL(*b); + break; + + } + if (ti_val_make_int(b, int_)) + ex_set_mem(e); + return e->nr; +} diff --git a/inc/ti/opr/xor.h b/inc/ti/opr/xor.h index 8cce4414..1697982c 100644 --- a/inc/ti/opr/xor.h +++ b/inc/ti/opr/xor.h @@ -1,3 +1,6 @@ +#ifndef TI_OPR_XOR_H_ +#define TI_OPR_XOR_H_ + #include static int opr__xor(ti_val_t * a, ti_val_t ** b, ex_t * e, _Bool inplace) @@ -96,3 +99,5 @@ static int opr__xor(ti_val_t * a, ti_val_t ** b, ex_t * e, _Bool inplace) ex_set_mem(e); return e->nr; } + +#endif /* TI_OPR_XOR_H_ */ diff --git a/inc/ti/version.h b/inc/ti/version.h index a007b61c..34d00e5a 100644 --- a/inc/ti/version.h +++ b/inc/ti/version.h @@ -25,7 +25,7 @@ * "-rc0" * "" */ -#define TI_VERSION_PRE_RELEASE "-alpha14" +#define TI_VERSION_PRE_RELEASE "-alpha15" #define TI_MAINTAINER \ "Jeroen van der Heijden " diff --git a/itest/test_operators.py b/itest/test_operators.py index 73b94d33..7ea9afae 100755 --- a/itest/test_operators.py +++ b/itest/test_operators.py @@ -365,5 +365,31 @@ async def test_bit_operations(self, client): !~1; """) + async def test_bitshift(self, client): + res = await client.query(r"""//ti + [ + 1 << 2, + 2 << 3 / 3, + 3 / 3 << 2, + 6 >> 1, + 10 >> 2 << 2, + ]; + """) + self.assertEqual(res, [ + 1 << 2, + 2 << 3 // 3, + 3 // 3 << 2, + 6 >> 1, + 10 >> 2 << 2, + ]) + + with self.assertRaisesRegex( + TypeError, + r'bitwise `<<` not supported between `float` and `int`'): + await client.query(r"""//ti + 3.0 << 1; + """) + + if __name__ == '__main__': run_test(TestOperators()) diff --git a/src/langdef/compat.c b/src/langdef/compat.c index 52cc39e9..9f5dbb01 100644 --- a/src/langdef/compat.c +++ b/src/langdef/compat.c @@ -111,14 +111,14 @@ cleri_grammar_t * compile_compat(void) ); cleri_t * opr0_mul_div_mod = cleri_tokens(CLERI_GID_OPR0_MUL_DIV_MOD, "* / %"); cleri_t * opr1_add_sub = cleri_tokens(CLERI_GID_OPR1_ADD_SUB, "+ -"); - cleri_t * opr2_bitwise_and = cleri_tokens(CLERI_GID_OPR2_BITWISE_AND, "&"); - cleri_t * opr3_bitwise_xor = cleri_tokens(CLERI_GID_OPR3_BITWISE_XOR, "^"); - cleri_t * opr4_bitwise_or = cleri_tokens(CLERI_GID_OPR4_BITWISE_OR, "|"); - cleri_t * opr5_compare = cleri_tokens(CLERI_GID_OPR5_COMPARE, "== != <= >= < >"); - cleri_t * opr6_cmp_and = cleri_token(CLERI_GID_OPR6_CMP_AND, "&&"); - cleri_t * opr7_cmp_or = cleri_token(CLERI_GID_OPR7_CMP_OR, "||"); + cleri_t * opr2_bitwise_and = cleri_tokens(CLERI_GID_OPR3_BITWISE_AND, "&"); + cleri_t * opr3_bitwise_xor = cleri_tokens(CLERI_GID_OPR4_BITWISE_XOR, "^"); + cleri_t * opr4_bitwise_or = cleri_tokens(CLERI_GID_OPR5_BITWISE_OR, "|"); + cleri_t * opr5_compare = cleri_tokens(CLERI_GID_OPR6_COMPARE, "== != <= >= < >"); + cleri_t * opr6_cmp_and = cleri_token(CLERI_GID_OPR7_CMP_AND, "&&"); + cleri_t * opr7_cmp_or = cleri_token(CLERI_GID_OPR8_CMP_OR, "||"); cleri_t * opr8_ternary = cleri_sequence( - CLERI_GID_OPR8_TERNARY, + CLERI_GID_OPR9_TERNARY, 3, x_ternary, CLERI_THIS, diff --git a/src/langdef/langdef.c b/src/langdef/langdef.c index 9584e435..e0db6750 100644 --- a/src/langdef/langdef.c +++ b/src/langdef/langdef.c @@ -5,7 +5,7 @@ * should be used with the libcleri module. * * Source class: LangDef - * Created at: 2024-02-05 10:13:48 + * Created at: 2024-02-11 20:55:25 */ #include @@ -111,14 +111,15 @@ cleri_grammar_t * compile_langdef(void) ); cleri_t * opr0_mul_div_mod = cleri_tokens(CLERI_GID_OPR0_MUL_DIV_MOD, "* / %"); cleri_t * opr1_add_sub = cleri_tokens(CLERI_GID_OPR1_ADD_SUB, "+ -"); - cleri_t * opr2_bitwise_and = cleri_tokens(CLERI_GID_OPR2_BITWISE_AND, "&"); - cleri_t * opr3_bitwise_xor = cleri_tokens(CLERI_GID_OPR3_BITWISE_XOR, "^"); - cleri_t * opr4_bitwise_or = cleri_tokens(CLERI_GID_OPR4_BITWISE_OR, "|"); - cleri_t * opr5_compare = cleri_tokens(CLERI_GID_OPR5_COMPARE, "== != <= >= < >"); - cleri_t * opr6_cmp_and = cleri_token(CLERI_GID_OPR6_CMP_AND, "&&"); - cleri_t * opr7_cmp_or = cleri_token(CLERI_GID_OPR7_CMP_OR, "||"); - cleri_t * opr8_ternary = cleri_sequence( - CLERI_GID_OPR8_TERNARY, + cleri_t * opr2_bitwise_shift = cleri_tokens(CLERI_GID_OPR2_BITWISE_SHIFT, "<< >>"); + cleri_t * opr3_bitwise_and = cleri_tokens(CLERI_GID_OPR3_BITWISE_AND, "&"); + cleri_t * opr4_bitwise_xor = cleri_tokens(CLERI_GID_OPR4_BITWISE_XOR, "^"); + cleri_t * opr5_bitwise_or = cleri_tokens(CLERI_GID_OPR5_BITWISE_OR, "|"); + cleri_t * opr6_compare = cleri_tokens(CLERI_GID_OPR6_COMPARE, "== != <= >= < >"); + cleri_t * opr7_cmp_and = cleri_token(CLERI_GID_OPR7_CMP_AND, "&&"); + cleri_t * opr8_cmp_or = cleri_token(CLERI_GID_OPR8_CMP_OR, "||"); + cleri_t * opr9_ternary = cleri_sequence( + CLERI_GID_OPR9_TERNARY, 3, x_ternary, CLERI_THIS, @@ -131,14 +132,15 @@ cleri_grammar_t * compile_langdef(void) cleri_choice( CLERI_NONE, CLERI_FIRST_MATCH, - 9, - opr8_ternary, - opr7_cmp_or, - opr6_cmp_and, - opr5_compare, - opr4_bitwise_or, - opr3_bitwise_xor, - opr2_bitwise_and, + 10, + opr9_ternary, + opr8_cmp_or, + opr7_cmp_and, + opr2_bitwise_shift, + opr6_compare, + opr5_bitwise_or, + opr4_bitwise_xor, + opr3_bitwise_and, opr1_add_sub, opr0_mul_div_mod ), diff --git a/src/langdef/translate.c b/src/langdef/translate.c index 11869237..98334c3c 100644 --- a/src/langdef/translate.c +++ b/src/langdef/translate.c @@ -12,12 +12,13 @@ const char * langdef_translate(cleri_t * elem) case CLERI_GID_K_CONTINUE: case CLERI_GID_OPR0_MUL_DIV_MOD: case CLERI_GID_OPR1_ADD_SUB: - case CLERI_GID_OPR2_BITWISE_AND: - case CLERI_GID_OPR3_BITWISE_XOR: - case CLERI_GID_OPR4_BITWISE_OR: - case CLERI_GID_OPR5_COMPARE: - case CLERI_GID_OPR6_CMP_AND: - case CLERI_GID_OPR7_CMP_OR: + case CLERI_GID_OPR2_BITWISE_SHIFT: + case CLERI_GID_OPR3_BITWISE_AND: + case CLERI_GID_OPR4_BITWISE_XOR: + case CLERI_GID_OPR5_BITWISE_OR: + case CLERI_GID_OPR6_COMPARE: + case CLERI_GID_OPR7_CMP_AND: + case CLERI_GID_OPR8_CMP_OR: case CLERI_GID_T_FALSE: case CLERI_GID_T_INT: case CLERI_GID_T_NIL: diff --git a/src/ti/do.c b/src/ti/do.c index 5eadb3bb..294fccb6 100644 --- a/src/ti/do.c +++ b/src/ti/do.c @@ -17,6 +17,17 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include #include @@ -228,21 +239,6 @@ static inline int do__upd_prop( return 0; } -static inline int do__upd_vaddr( - ti_val_t ** vaddr, - ti_query_t * query, - cleri_node_t * tokens_nd, - ex_t * e) -{ - if (ti_opr_a_to_b(*vaddr, tokens_nd, &query->rval, e)) - return e->nr; - - ti_val_unsafe_gc_drop(*vaddr); - *vaddr = query->rval; - ti_incref(query->rval); - return 0; -} - static int do__name_assign(ti_query_t * query, cleri_node_t * nd, ex_t * e) { assert(nd->cl_obj->gid == CLERI_GID_NAME_OPT_MORE); @@ -700,6 +696,182 @@ int ti_do_operation(ti_query_t * query, cleri_node_t * nd, ex_t * e) return e->nr; } +int ti_do_bit_sl(ti_query_t * query, cleri_node_t * nd, ex_t * e) +{ + ti_val_t * a; + if (ti_do_statement(query, nd->children, e)) + return e->nr; + + a = query->rval; + query->rval = NULL; + + if (ti_do_statement(query, nd->children->next->next, e) == 0) + (void) opr__sl(a, &query->rval, e); + + ti_val_unsafe_drop(a); + return e->nr; +} + +int ti_do_bit_sr(ti_query_t * query, cleri_node_t * nd, ex_t * e) +{ + ti_val_t * a; + if (ti_do_statement(query, nd->children, e)) + return e->nr; + + a = query->rval; + query->rval = NULL; + + if (ti_do_statement(query, nd->children->next->next, e) == 0) + (void) opr__sr(a, &query->rval, e); + + ti_val_unsafe_drop(a); + return e->nr; +} + +int ti_do_bit_and(ti_query_t * query, cleri_node_t * nd, ex_t * e) +{ + ti_val_t * a; + if (ti_do_statement(query, nd->children, e)) + return e->nr; + + a = query->rval; + query->rval = NULL; + + if (ti_do_statement(query, nd->children->next->next, e) == 0) + (void) opr__and(a, &query->rval, e, false); + + ti_val_unsafe_drop(a); + return e->nr; +} + +int ti_do_bit_xor(ti_query_t * query, cleri_node_t * nd, ex_t * e) +{ + ti_val_t * a; + if (ti_do_statement(query, nd->children, e)) + return e->nr; + + a = query->rval; + query->rval = NULL; + + if (ti_do_statement(query, nd->children->next->next, e) == 0) + (void) opr__xor(a, &query->rval, e, false); + + ti_val_unsafe_drop(a); + return e->nr; +} + +int ti_do_bit_or(ti_query_t * query, cleri_node_t * nd, ex_t * e) +{ + ti_val_t * a; + if (ti_do_statement(query, nd->children, e)) + return e->nr; + + a = query->rval; + query->rval = NULL; + + if (ti_do_statement(query, nd->children->next->next, e) == 0) + (void) opr__or(a, &query->rval, e, false); + + ti_val_unsafe_drop(a); + return e->nr; +} + +int ti_do_compare_eq(ti_query_t * query, cleri_node_t * nd, ex_t * e) +{ + ti_val_t * a; + if (ti_do_statement(query, nd->children, e)) + return e->nr; + + a = query->rval; + query->rval = NULL; + + if (ti_do_statement(query, nd->children->next->next, e) == 0) + (void) opr__eq(a, &query->rval, e); + + ti_val_unsafe_drop(a); + return e->nr; +} + +int ti_do_compare_ne(ti_query_t * query, cleri_node_t * nd, ex_t * e) +{ + ti_val_t * a; + if (ti_do_statement(query, nd->children, e)) + return e->nr; + + a = query->rval; + query->rval = NULL; + + if (ti_do_statement(query, nd->children->next->next, e) == 0) + (void) opr__ne(a, &query->rval, e); + + ti_val_unsafe_drop(a); + return e->nr; +} + +int ti_do_compare_lt(ti_query_t * query, cleri_node_t * nd, ex_t * e) +{ + ti_val_t * a; + if (ti_do_statement(query, nd->children, e)) + return e->nr; + + a = query->rval; + query->rval = NULL; + + if (ti_do_statement(query, nd->children->next->next, e) == 0) + (void) opr__lt(a, &query->rval, e); + + ti_val_unsafe_drop(a); + return e->nr; +} + +int ti_do_compare_le(ti_query_t * query, cleri_node_t * nd, ex_t * e) +{ + ti_val_t * a; + if (ti_do_statement(query, nd->children, e)) + return e->nr; + + a = query->rval; + query->rval = NULL; + + if (ti_do_statement(query, nd->children->next->next, e) == 0) + (void) opr__le(a, &query->rval, e); + + ti_val_unsafe_drop(a); + return e->nr; +} + +int ti_do_compare_gt(ti_query_t * query, cleri_node_t * nd, ex_t * e) +{ + ti_val_t * a; + if (ti_do_statement(query, nd->children, e)) + return e->nr; + + a = query->rval; + query->rval = NULL; + + if (ti_do_statement(query, nd->children->next->next, e) == 0) + (void) opr__gt(a, &query->rval, e); + + ti_val_unsafe_drop(a); + return e->nr; +} + +int ti_do_compare_ge(ti_query_t * query, cleri_node_t * nd, ex_t * e) +{ + ti_val_t * a; + if (ti_do_statement(query, nd->children, e)) + return e->nr; + + a = query->rval; + query->rval = NULL; + + if (ti_do_statement(query, nd->children->next->next, e) == 0) + (void) opr__ge(a, &query->rval, e); + + ti_val_unsafe_drop(a); + return e->nr; +} + int ti_do_compare_and(ti_query_t * query, cleri_node_t * nd, ex_t * e) { if (ti_do_statement(query, nd->children, e) || @@ -1492,13 +1664,18 @@ static int do__var_assign(ti_query_t * query, cleri_node_t * nd, ex_t * e) return e->nr; } - if (do__upd_vaddr( - &prop->val, - query, - tokens_nd, - e)) + if (ti_opr_a_to_b(prop->val, tokens_nd, &query->rval, e)) return e->nr; + /* ti_val_unsafe_gc_drop */ + if (!--prop->val->ref) + ti_val(prop->val)->destroy(prop->val); + else + ti_thing_may_push_gc((ti_thing_t *) prop->val); + + prop->val = query->rval; + ti_incref(query->rval); + if (thing->id) { ti_task_t * task = ti_task_get_task(query->change, thing); diff --git a/src/ti/fmt.c b/src/ti/fmt.c index 003f0750..ca01d605 100644 --- a/src/ti/fmt.c +++ b/src/ti/fmt.c @@ -436,7 +436,7 @@ static int fmt__operations(ti_fmt_t * fmt, cleri_node_t * nd) { cleri_node_t * node; - if (nd->children->next->cl_obj->gid == CLERI_GID_OPR8_TERNARY) + if (nd->children->next->cl_obj->gid == CLERI_GID_OPR9_TERNARY) { cleri_node_t * nd_true = nd->children->next->children->next, diff --git a/src/ti/ncache.c b/src/ti/ncache.c index 15999dc7..b6b1eec2 100644 --- a/src/ti/ncache.c +++ b/src/ti/ncache.c @@ -390,7 +390,7 @@ static int ncache__operations( ex_t * e) { uint32_t gid = nd->children->next->cl_obj->gid; - if (gid == CLERI_GID_OPR8_TERNARY && + if (gid == CLERI_GID_OPR9_TERNARY && ncache__statement( syntax, vcache, diff --git a/src/ti/opr.c b/src/ti/opr.c index 4facad08..c7354c59 100644 --- a/src/ti/opr.c +++ b/src/ti/opr.c @@ -4,14 +4,8 @@ #include #include #include -#include -#include -#include -#include -#include #include #include -#include #include #include #include @@ -27,14 +21,8 @@ int ti_opr_a_to_b(ti_val_t * a, cleri_node_t * nd, ti_val_t ** b, ex_t * e) { - /* - * TODO: this code can be pre-compiled and bind the correct function so - * a call to this function is no longer required; - */ switch (*nd->str) { - case '!': - return opr__ne(a, b, e); case '%': return opr__mod(a, b, e); case '&': @@ -47,12 +35,6 @@ int ti_opr_a_to_b(ti_val_t * a, cleri_node_t * nd, ti_val_t ** b, ex_t * e) return opr__sub(a, b, e, nd->len == 2); case '/': return opr__div(a, b, e); - case '<': - return nd->len == 1 ? opr__lt(a, b, e) : opr__le(a, b, e); - case '=': - return opr__eq(a, b, e); - case '>': - return nd->len == 1 ? opr__gt(a, b, e) : opr__ge(a, b, e); case '^': return opr__xor(a, b, e, nd->len == 2); case '|': diff --git a/src/ti/qbind.c b/src/ti/qbind.c index 0755eebd..f102d4f7 100644 --- a/src/ti/qbind.c +++ b/src/ti/qbind.c @@ -810,7 +810,35 @@ static _Bool qbind__swap(cleri_node_t ** parent, uint32_t parent_gid) * operations must be handled from left-to-right. # bug #271 */ return gid > parent_gid || ( - gid == parent_gid && gid != CLERI_GID_OPR8_TERNARY); + gid == parent_gid && gid != CLERI_GID_OPR9_TERNARY); +} + +static inline ti_do_cb qbind__find_operation(cleri_node_t * nd) +{ + switch(nd->cl_obj->gid) + { + case CLERI_GID_OPR0_MUL_DIV_MOD: + case CLERI_GID_OPR1_ADD_SUB: return ti_do_operation; + case CLERI_GID_OPR2_BITWISE_SHIFT: + return *nd->str == '<' ? ti_do_bit_sl : ti_do_bit_sr; + case CLERI_GID_OPR3_BITWISE_AND: return ti_do_bit_and; + case CLERI_GID_OPR4_BITWISE_XOR: return ti_do_bit_xor; + case CLERI_GID_OPR5_BITWISE_OR: return ti_do_bit_or; + case CLERI_GID_OPR6_COMPARE: + switch(*nd->str) + { + case '=': return ti_do_compare_eq; + case '!': return ti_do_compare_ne; + case '<': return nd->len == 1 ? ti_do_compare_lt : ti_do_compare_le; + case '>': return nd->len == 1 ? ti_do_compare_gt : ti_do_compare_ge; + } + break; + case CLERI_GID_OPR7_CMP_AND: return ti_do_compare_and; + case CLERI_GID_OPR8_CMP_OR: return ti_do_compare_or; + case CLERI_GID_OPR9_TERNARY: return ti_do_ternary; + } + assert(0); + return NULL; } /* @@ -822,7 +850,7 @@ static _Bool qbind__swap(cleri_node_t ** parent, uint32_t parent_gid) * The language uses keys like: * - CLERI_GID_OPR0_MUL_DIV_MOD * - CLERI_GID_OPR1_ADD_SUB - * - CLERI_GID_OPR2_BITWISE_AND, + * - CLERI_GID_OPR2_BITWISE_SHIFT, * - etc.... * The keys are numbered so the corresponding ID's can be used as order. */ @@ -831,28 +859,17 @@ static _Bool qbind__operations( cleri_node_t ** parent, uint32_t parent_gid) { - static const ti_do_cb operation_cb[9] = { - ti_do_operation, /* CLERI_GID_OPR0_MUL_DIV_MOD */ - ti_do_operation, /* CLERI_GID_OPR1_ADD_SUB */ - ti_do_operation, /* CLERI_GID_OPR2_BITWISE_AND */ - ti_do_operation, /* CLERI_GID_OPR3_BITWISE_XOR */ - ti_do_operation, /* CLERI_GID_OPR4_BITWISE_OR */ - ti_do_operation, /* CLERI_GID_OPR5_COMPARE */ - ti_do_compare_and, /* CLERI_GID_OPR6_CMP_AND */ - ti_do_compare_or, /* CLERI_GID_OPR7_CMP_OR */ - ti_do_ternary, /* CLERI_GID_OPR8_TERNARY */ - }; uint32_t gid = (*parent)->children->next->cl_obj->gid; cleri_node_t * childb = (*parent)->children->next->next; - (*parent)->data = operation_cb[gid - CLERI_GID_OPR0_MUL_DIV_MOD]; + (*parent)->data = qbind__find_operation((*parent)->children->next); assert(gid >= CLERI_GID_OPR0_MUL_DIV_MOD && - gid <= CLERI_GID_OPR8_TERNARY); + gid <= CLERI_GID_OPR9_TERNARY); qbind__statement(qbind, (*parent)->children); - if (gid == CLERI_GID_OPR8_TERNARY) + if (gid == CLERI_GID_OPR9_TERNARY) qbind__statement( qbind, (*parent)->children->next->children->next); @@ -871,7 +888,7 @@ static _Bool qbind__operations( gid = (*parent)->children->next->cl_obj->gid; assert(gid >= CLERI_GID_OPR0_MUL_DIV_MOD && - gid <= CLERI_GID_OPR8_TERNARY); + gid <= CLERI_GID_OPR9_TERNARY); syntax_childa = &(*parent)->children->children; childb->children = *syntax_childa; @@ -893,7 +910,7 @@ static _Bool qbind__operations( * operations must be handled from left-to-right. # bug #271 */ return gid > parent_gid || ( - gid == parent_gid && gid != CLERI_GID_OPR8_TERNARY); + gid == parent_gid && gid != CLERI_GID_OPR9_TERNARY); } /*