diff --git a/src/Makefile.am b/src/Makefile.am index 44d1158..c14e588 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -22,6 +22,9 @@ expression/hklr_op_mod.c \ expression/hklr_op_not_equal.c \ expression/hklr_op_equal.c \ expression/hklr_op_coalesce.c \ +expression/hklr_op_bitwise_or.c \ +expression/hklr_op_bitwise_and.c \ +expression/hklr_op_bitwise_xor.c \ expression/hklr_as_integer.c \ expression/hklr_as_real.c \ expression/hklr_as_string.c \ diff --git a/src/expression/hklr_op_bitwise_and.c b/src/expression/hklr_op_bitwise_and.c new file mode 100644 index 0000000..fbe7366 --- /dev/null +++ b/src/expression/hklr_op_bitwise_and.c @@ -0,0 +1,56 @@ +#include + +#include "hkl_value.h" + +HklValue* hklr_op_bitwise_and(HklValue* left_value, HklValue* right_value) +{ + HklValue* result = NULL; + bool left_updated = false, right_updated = false; + + // Dereference left and right sides + if (left_value->type == HKL_TYPE_REF) + { + left_updated = true; + left_value = hklr_object_dereference(left_value->as.object); + } + + if (right_value->type == HKL_TYPE_REF) + { + right_updated = true; + right_value = hklr_object_dereference(right_value->as.object); + } + + switch (left_value->type) + { + case HKL_TYPE_INT: + switch(right_value->type) + { + case HKL_TYPE_INT: + result = hkl_value_new(HKL_TYPE_INT, + left_value->as.integer & right_value->as.integer); + break; + + case HKL_TYPE_REAL: + case HKL_TYPE_STRING: + default: + assert(false); + break; + } + break; // HKL_TYPE_INT + default: + assert(false); + break; + } + + if (left_updated) + { + hkl_value_free(left_value); + } + + if (right_updated) + { + hkl_value_free(right_value); + } + + return result; +} \ No newline at end of file diff --git a/src/expression/hklr_op_bitwise_or.c b/src/expression/hklr_op_bitwise_or.c new file mode 100644 index 0000000..a2a0622 --- /dev/null +++ b/src/expression/hklr_op_bitwise_or.c @@ -0,0 +1,56 @@ +#include + +#include "hkl_value.h" + +HklValue* hklr_op_bitwise_or(HklValue* left_value, HklValue* right_value) +{ + HklValue* result = NULL; + bool left_updated = false, right_updated = false; + + // Dereference left and right sides + if (left_value->type == HKL_TYPE_REF) + { + left_updated = true; + left_value = hklr_object_dereference(left_value->as.object); + } + + if (right_value->type == HKL_TYPE_REF) + { + right_updated = true; + right_value = hklr_object_dereference(right_value->as.object); + } + + switch (left_value->type) + { + case HKL_TYPE_INT: + switch(right_value->type) + { + case HKL_TYPE_INT: + result = hkl_value_new(HKL_TYPE_INT, + left_value->as.integer | right_value->as.integer); + break; + + case HKL_TYPE_REAL: + case HKL_TYPE_STRING: + default: + assert(false); + break; + } + break; // HKL_TYPE_INT + default: + assert(false); + break; + } + + if (left_updated) + { + hkl_value_free(left_value); + } + + if (right_updated) + { + hkl_value_free(right_value); + } + + return result; +} \ No newline at end of file diff --git a/src/expression/hklr_op_bitwise_xor.c b/src/expression/hklr_op_bitwise_xor.c new file mode 100644 index 0000000..17990a3 --- /dev/null +++ b/src/expression/hklr_op_bitwise_xor.c @@ -0,0 +1,56 @@ +#include + +#include "hkl_value.h" + +HklValue* hklr_op_bitwise_xor(HklValue* left_value, HklValue* right_value) +{ + HklValue* result = NULL; + bool left_updated = false, right_updated = false; + + // Dereference left and right sides + if (left_value->type == HKL_TYPE_REF) + { + left_updated = true; + left_value = hklr_object_dereference(left_value->as.object); + } + + if (right_value->type == HKL_TYPE_REF) + { + right_updated = true; + right_value = hklr_object_dereference(right_value->as.object); + } + + switch (left_value->type) + { + case HKL_TYPE_INT: + switch(right_value->type) + { + case HKL_TYPE_INT: + result = hkl_value_new(HKL_TYPE_INT, + left_value->as.integer ^ right_value->as.integer); + break; + + case HKL_TYPE_REAL: + case HKL_TYPE_STRING: + default: + assert(false); + break; + } + break; // HKL_TYPE_INT + default: + assert(false); + break; + } + + if (left_updated) + { + hkl_value_free(left_value); + } + + if (right_updated) + { + hkl_value_free(right_value); + } + + return result; +} \ No newline at end of file diff --git a/src/hklr_expression.c b/src/hklr_expression.c index c716b53..d122eb7 100644 --- a/src/hklr_expression.c +++ b/src/hklr_expression.c @@ -30,6 +30,11 @@ extern HklValue* hklr_op_not_equal(HklValue* left_value, HklValue* right_value); extern HklValue* hklr_op_equal(HklValue* left_value, HklValue* right_value); extern HklValue* hklr_op_coalesce(HklValue* left_value, HklValue* right_value); +extern HklValue* hklr_op_bitwise_or(HklValue* left_value, HklValue* right_value); +extern HklValue* hklr_op_bitwise_and(HklValue* left_value, HklValue* right_value); +extern HklValue* hklr_op_bitwise_xor(HklValue* left_value, HklValue* right_value); + + HklrExpression* hklr_expression_new(HklExpressionType type, ...) { assert(type != HKL_EXPR_NONE); @@ -372,6 +377,19 @@ HklValue* hklr_expression_eval(HklrExpression* expr) return hklr_op_typeof(value); break; // HKL_OP_TYPE + case HKL_OP_BITWISE_NOT: + switch (value->type) + { + case HKL_TYPE_INT: + value->as.integer = ~value->as.integer; + return value; + break; + + default: + assert(false); + break; + } + default: assert(false); break; @@ -432,6 +450,18 @@ HklValue* hklr_expression_eval(HklrExpression* expr) right_value->type = HKL_TYPE_NIL; } break; + + case HKL_OP_BITWISE_AND: + result = hklr_op_bitwise_and(left_value, right_value); + break; + case HKL_OP_BITWISE_OR: + result = hklr_op_bitwise_or(left_value, right_value); + break; + + case HKL_OP_BITWISE_XOR: + result = hklr_op_bitwise_xor(left_value, right_value); + break; + case HKL_OP_AS: { assert(right_value->type == HKL_TYPE_TYPE); diff --git a/src/y.tab.y b/src/y.tab.y index c21a829..ab52995 100644 --- a/src/y.tab.y +++ b/src/y.tab.y @@ -442,6 +442,25 @@ expr: { $$ = hklr_expression_new(HKL_EXPR_BINARY, $1, HKL_OP_AS, $3); } + + | expr HKL_T_BITWISE_AND expr + { + $$ = hklr_expression_new(HKL_EXPR_BINARY, $1, HKL_OP_BITWISE_AND, $3); + } + | expr HKL_T_BITWISE_OR expr + { + $$ = hklr_expression_new(HKL_EXPR_BINARY, $1, HKL_OP_BITWISE_OR, $3); + } + | expr HKL_T_BITWISE_XOR expr + { + $$ = hklr_expression_new(HKL_EXPR_BINARY, $1, HKL_OP_BITWISE_XOR, $3); + } + | HKL_T_BITWISE_NOT expr %prec UNARY_OPS + { + $$ = hklr_expression_new(HKL_EXPR_UNARY, HKL_OP_BITWISE_NOT, $2); + } + + | HKL_T_MINUS expr %prec UNARY_OPS { $$ = hklr_expression_new(HKL_EXPR_UNARY, HKL_OP_UNARY_MINUS, $2);