Add bit ops to binary

This commit is contained in:
Krzosa Karol
2022-06-03 14:57:10 +02:00
parent 84b393ce2f
commit cc387af8ed
2 changed files with 48 additions and 26 deletions

View File

@@ -1,12 +1,12 @@
unary_test :: () unary_test :: ()
int_val :: 125152553512512512512 // @todo // int_val :: 125152553512512512512 // @todo bit ints
int_val :: 141
float_val :: 124.42 float_val :: 124.42
conversion: F64 = -+int_val conversion: F64 = -+int_val
float2 := -float_val float2 := -float_val
unsigned: Int = -+-+-int_val unsigned: Int = -+-+-int_val
// uns: U64 = -int_val // uns: U64 = -int_val
// int_float: S64 = float_val // int_float: S64 = float_val
// string :: -"Thing" // string :: -"Thing"
@@ -16,7 +16,11 @@ unary_test :: ()
binary_test :: () binary_test :: ()
int_val :: 1000 int_val :: 1000
add :: int_val + 10 + 2.242 add :: int_val + 10 + 2.242 + 124
mul :: 4 * 2
bit_and :: 3 & 1
bit_or :: 1 | 4
bit_xor :: 8 ^ 7

View File

@@ -21,7 +21,7 @@ convert_untyped(Token *pos, Value a, Ast_Resolved_Type *new_type){
switch(new_type->kind){ switch(new_type->kind){
case TYPE_UNTYPED_INT: break; case TYPE_UNTYPED_INT: break;
CASE_CONVERT(pos, a.int_val, a.type->kind, a.s64_val, TYPE_INT, TYPE_INT_MIN, TYPE_INT_MAX) CASE_CONVERT(pos, a.int_val, a.type->kind, a.s64_val, TYPE_INT, TYPE_INT_MIN, TYPE_INT_MAX)
CASE_CONVERT(pos, a.int_val, a.type->kind, a.u64_val, TYPE_UINT, TYPE_UINT_MIN, TYPE_INT_MAX) CASE_CONVERT(pos, a.int_val, a.type->kind, a.u64_val, TYPE_UINT, TYPE_UINT_MIN, TYPE_INT_MAX) // @todo big int
CASE_CONVERT(pos, a.int_val, a.type->kind, a.s8_val , TYPE_S8 , S8MIN, S8MAX) CASE_CONVERT(pos, a.int_val, a.type->kind, a.s8_val , TYPE_S8 , S8MIN, S8MAX)
CASE_CONVERT(pos, a.int_val, a.type->kind, a.s16_val, TYPE_S16, S16MIN, S16MAX) CASE_CONVERT(pos, a.int_val, a.type->kind, a.s16_val, TYPE_S16, S16MIN, S16MAX)
CASE_CONVERT(pos, a.int_val, a.type->kind, a.s32_val, TYPE_S32, S32MIN, S32MAX) CASE_CONVERT(pos, a.int_val, a.type->kind, a.s32_val, TYPE_S32, S32MIN, S32MAX)
@@ -29,7 +29,7 @@ convert_untyped(Token *pos, Value a, Ast_Resolved_Type *new_type){
CASE_CONVERT(pos, a.int_val, a.type->kind, a.u8_val , TYPE_U8 , U8MIN, U8MAX) CASE_CONVERT(pos, a.int_val, a.type->kind, a.u8_val , TYPE_U8 , U8MIN, U8MAX)
CASE_CONVERT(pos, a.int_val, a.type->kind, a.u16_val, TYPE_U16, U16MIN, U16MAX) CASE_CONVERT(pos, a.int_val, a.type->kind, a.u16_val, TYPE_U16, U16MIN, U16MAX)
CASE_CONVERT(pos, a.int_val, a.type->kind, a.u32_val, TYPE_U32, U32MIN, U32MAX) CASE_CONVERT(pos, a.int_val, a.type->kind, a.u32_val, TYPE_U32, U32MIN, U32MAX)
CASE_CONVERT(pos, a.int_val, a.type->kind, a.u64_val, TYPE_U64, U64MIN, U64MAX) CASE_CONVERT(pos, a.int_val, a.type->kind, a.u64_val, TYPE_U64, U64MIN, U64MAX) // @todo big int
invalid_default_case; invalid_default_case;
} }
} }
@@ -71,11 +71,11 @@ value_get_int(Value value){
case TYPE_S32:result = value.s32_val; break; case TYPE_S32:result = value.s32_val; break;
case TYPE_S16:result = value.s16_val; break; case TYPE_S16:result = value.s16_val; break;
case TYPE_S8:result = value.s8_val; break; case TYPE_S8:result = value.s8_val; break;
case TYPE_U64:result = value.u64_val; break;// @todo Need big int case TYPE_U64:assert(value.u64_val <= S64MAX); result = value.u64_val; break; // @todo big int
case TYPE_U32:result = value.u32_val; break; case TYPE_U32:result = value.u32_val; break;
case TYPE_U16:result = value.u16_val; break; case TYPE_U16:result = value.u16_val; break;
case TYPE_U8:result = value.u8_val; break; case TYPE_U8:result = value.u8_val; break;
case TYPE_UINT:result = value.u64_val; break; case TYPE_UINT:result = value.u64_val; break; // @todo big int
default: invalid_codepath; default: invalid_codepath;
} }
return result; return result;
@@ -97,10 +97,31 @@ function Value
eval_binary(Token *pos, Token_Kind op, Value a, Value b){ eval_binary(Token *pos, Token_Kind op, Value a, Value b){
if(!(is_numeric(a.type) && is_numeric(b.type))) parsing_error(pos, "Constant application of binary %s on values of type %s is not allowed", token_kind_string(op).str, docname(a.type)); if(!(is_numeric(a.type) && is_numeric(b.type))) parsing_error(pos, "Constant application of binary %s on values of type %s is not allowed", token_kind_string(op).str, docname(a.type));
Ast_Resolved_Type *final_type = 0;
Value before_conversion;
if(is_int(a.type) && is_int(b.type)) {
before_conversion.type = untyped_int;
final_type = untyped_int;
}
else{
before_conversion.type = untyped_float;
final_type = untyped_float;
}
if(is_typed(a.type) && is_typed(b.type)){
if(a.type != b.type) parsing_error(pos, "Type mismatch in binary operation %s - left: %s right: %s", token_kind_string(op).str, docname(a.type), docname(b.type));
else final_type = a.type;
}
else if(is_typed(a.type) || is_typed(b.type)){
not_implemented;
}
S64 left_int = value_get_int(a); S64 left_int = value_get_int(a);
S64 right_int = value_get_int(b); S64 right_int = value_get_int(b);
F64 left_float = value_get_float(a); F64 left_float = value_get_float(a);
F64 right_float = value_get_float(b); F64 right_float = value_get_float(b);
// @WARNING: When introducing big ints & | ^ will be problematic
switch(op){ switch(op){
case TK_Add: { case TK_Add: {
@@ -123,29 +144,26 @@ eval_binary(Token *pos, Token_Kind op, Value a, Value b){
left_int = left_int % right_int; left_int = left_int % right_int;
left_float = fmod(left_float, right_float); left_float = fmod(left_float, right_float);
} break; } break;
case TK_BitAnd: {
left_int = left_int & right_int;
if(before_conversion.type == untyped_float) parsing_error(pos, "%s cant be performed on [Untyped_Float]", token_kind_string(op).str);
} break;
case TK_BitOr: {
left_int = left_int | right_int;
if(before_conversion.type == untyped_float) parsing_error(pos, "%s cant be performed on [Untyped_Float]", token_kind_string(op).str);
} break;
case TK_BitXor: {
left_int = left_int ^ right_int;
if(before_conversion.type == untyped_float) parsing_error(pos, "%s cant be performed on [Untyped_Float]", token_kind_string(op).str);
} break;
invalid_default_case; invalid_default_case;
} }
Ast_Resolved_Type *final_type = 0; if(before_conversion.type == untyped_float){
Value before_conversion;
if(is_int(a.type) && is_int(b.type)) {
before_conversion.type = untyped_int;
before_conversion.int_val = left_int;
final_type = untyped_int;
}
else{
before_conversion.type = untyped_float;
before_conversion.f64_val = left_float; before_conversion.f64_val = left_float;
final_type = untyped_float; } else {
} assert(before_conversion.type == untyped_int);
before_conversion.int_val = left_int;
if(is_typed(a.type) && is_typed(b.type)){
if(a.type != b.type) parsing_error(pos, "Type mismatch in binary operation %s - left: %s right: %s", token_kind_string(op).str, docname(a.type), docname(b.type));
else final_type = a.type;
}
else if(is_typed(a.type) || is_typed(b.type)){
not_implemented;
} }
Value result = convert_untyped(pos, before_conversion, final_type); Value result = convert_untyped(pos, before_conversion, final_type);