Skip to content

Commit

Permalink
Add Bit-wise Left and Right shift (#361)
Browse files Browse the repository at this point in the history
* implement bitshift

* Added tests

* Update changelog

* Upd translate

* Direct bind operation

* manual inline
  • Loading branch information
joente authored Feb 12, 2024
1 parent d3d81aa commit cda527f
Show file tree
Hide file tree
Showing 19 changed files with 419 additions and 114 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -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.
Expand Down
34 changes: 18 additions & 16 deletions grammar/grammar.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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'''/./;''')
Expand Down
17 changes: 9 additions & 8 deletions 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: 2024-02-05 10:13:48
* Created at: 2024-02-11 20:55:25
*/
#ifndef CLERI_EXPORT_LANGDEF_H_
#define CLERI_EXPORT_LANGDEF_H_
Expand Down Expand Up @@ -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,
Expand Down
11 changes: 11 additions & 0 deletions inc/ti/do.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
5 changes: 5 additions & 0 deletions inc/ti/opr/and.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
#ifndef TI_OPR_AND_H_
#define TI_OPR_AND_H_

#include <ti/opr/oprinc.h>

static int opr__and(ti_val_t * a, ti_val_t ** b, ex_t * e, _Bool inplace)
Expand Down Expand Up @@ -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_ */
5 changes: 5 additions & 0 deletions inc/ti/opr/or.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
#ifndef TI_OPR_OR_H_
#define TI_OPR_OR_H_

#include <ti/opr/oprinc.h>

static int opr__or(ti_val_t * a, ti_val_t ** b, ex_t * e, _Bool inplace)
Expand Down Expand Up @@ -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_ */
35 changes: 35 additions & 0 deletions inc/ti/opr/sl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#include <ti/opr/oprinc.h>

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;
}
35 changes: 35 additions & 0 deletions inc/ti/opr/sr.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#include <ti/opr/oprinc.h>

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;
}
5 changes: 5 additions & 0 deletions inc/ti/opr/xor.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
#ifndef TI_OPR_XOR_H_
#define TI_OPR_XOR_H_

#include <ti/opr/oprinc.h>

static int opr__xor(ti_val_t * a, ti_val_t ** b, ex_t * e, _Bool inplace)
Expand Down Expand Up @@ -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_ */
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 "-alpha14"
#define TI_VERSION_PRE_RELEASE "-alpha15"

#define TI_MAINTAINER \
"Jeroen van der Heijden <jeroen@cesbit.com>"
Expand Down
26 changes: 26 additions & 0 deletions itest/test_operators.py
Original file line number Diff line number Diff line change
Expand Up @@ -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())
14 changes: 7 additions & 7 deletions src/langdef/compat.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
36 changes: 19 additions & 17 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: 2024-02-05 10:13:48
* Created at: 2024-02-11 20:55:25
*/

#include <langdef/langdef.h>
Expand Down Expand Up @@ -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,
Expand All @@ -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
),
Expand Down
13 changes: 7 additions & 6 deletions src/langdef/translate.c
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
Loading

0 comments on commit cda527f

Please sign in to comment.