This commit is contained in:
Krzosa Karol
2022-06-06 09:17:34 +02:00
parent 6157325d8f
commit 325050300a
2 changed files with 104 additions and 93 deletions

View File

@@ -31,37 +31,6 @@ type_error(Token *token, Ast_Resolved_Type *expected, Ast_Resolved_Type *actual,
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Evaluating constant expressions // Evaluating constant expressions
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
function Value
convert_untyped(Token *pos, Value a, Ast_Resolved_Type *new_type){
// assert(a.type);
assert(new_type);
if(a.type == 0) return a;
if(is_typed(a.type)) return a;
if(is_int(a.type) && is_int(new_type)){
assert(a.type == untyped_int);
if(!bigint_fits_in_bits(&a.big_int_val, new_type->size*8, is_signed_int(new_type))){
parsing_error(pos, "Doesn't fit");
}
}
else if(is_int(a.type) && is_float(new_type)){
a.f64_val = bigint_as_float(&a.big_int_val); // @leak bigint
}
else if(is_float(a.type) && is_float(new_type)){
// nothing to do
}
else if(is_bool(a.type) && is_bool(new_type))
; // nothing to do
else if(is_string(a.type) && is_string(new_type))
; // nothing to do
else parsing_error(pos, "Type mismatch when converting from %s to %s", docname(a.type), docname(new_type));
a.type = new_type;
return a;
}
function Value function Value
value_bool(B32 v){ value_bool(B32 v){
Value value; Value value;
@@ -102,14 +71,41 @@ value_float(BigInt a){
return value; return value;
} }
function Value
convert_untyped(Token *pos, Value a, Ast_Resolved_Type *new_type){
assert(new_type);
if(a.type == 0) return a;
if(is_typed(a.type)) return a;
if(is_int(a.type) && is_int(new_type)){
assert(a.type == untyped_int);
if(!bigint_fits_in_bits(&a.big_int_val, new_type->size*8, is_signed_int(new_type))){
Scratch scratch;
const char *string = bigint_to_error_string(scratch, &a.big_int_val, 10);
parsing_error(pos, "Value %s doesn't fit in type %s", string, docname(new_type));
}
}
else if(is_int(a.type) && is_float(new_type))
a.f64_val = bigint_as_float(&a.big_int_val); // @leak bigint
else if(is_float(a.type) && is_float(new_type))
; // nothing to do
else if(is_bool(a.type) && is_bool(new_type))
; // nothing to do
else if(is_string(a.type) && is_string(new_type))
; // nothing to do
else parsing_error(pos, "Type mismatch when converting from %s to %s", docname(a.type), docname(new_type));
a.type = new_type;
return a;
}
function void function void
match_values(Value *a, Value *b){ match_values(Value *a, Value *b){
if(is_int(a->type) && is_float(b->type)){ if(is_int(a->type) && is_float(b->type))
*a = value_float(a->big_int_val); *a = value_float(a->big_int_val);
} else if(is_float(a->type) && is_int(b->type))
else if(is_float(a->type) && is_int(b->type)){
*b = value_float(b->big_int_val); *b = value_float(b->big_int_val);
}
} }
function Value function Value
@@ -119,9 +115,7 @@ compare_values(Token *pos, Token_Kind op, Value a, Value b){
B32 result = 0; B32 result = 0;
switch(a.type->kind){ switch(a.type->kind){
case TYPE_UNTYPED_INT: CASE_INT:{
case TYPE_S8:case TYPE_S16:case TYPE_S32:case TYPE_S64:
case TYPE_U8:case TYPE_U16:case TYPE_U32:case TYPE_U64:{
CmpRes cmp = bigint_cmp(&a.big_int_val, &b.big_int_val); CmpRes cmp = bigint_cmp(&a.big_int_val, &b.big_int_val);
switch(op){ switch(op){
case TK_LesserThenOrEqual: result = (cmp == CMP_LT) || (cmp == CMP_EQ); break; case TK_LesserThenOrEqual: result = (cmp == CMP_LT) || (cmp == CMP_EQ); break;
@@ -133,16 +127,14 @@ compare_values(Token *pos, Token_Kind op, Value a, Value b){
invalid_default_case; invalid_default_case;
} }
}break; }break;
case TYPE_UNTYPED_BOOL: CASE_BOOL:{
case TYPE_BOOL:{
switch(op){ switch(op){
case TK_Equals: result = a.bool_val == b.bool_val; break; case TK_Equals: result = a.bool_val == b.bool_val; break;
case TK_NotEquals: result = a.bool_val != b.bool_val; break; case TK_NotEquals: result = a.bool_val != b.bool_val; break;
invalid_default_case; invalid_default_case;
} }
}break; }break;
case TYPE_UNTYPED_FLOAT: CASE_FLOAT:{
case TYPE_F32: case TYPE_F64:{
switch(op){ switch(op){
case TK_LesserThenOrEqual: result = a.f64_val <= b.f64_val; break; case TK_LesserThenOrEqual: result = a.f64_val <= b.f64_val; break;
case TK_GreaterThenOrEqual: result = a.f64_val >= b.f64_val; break; case TK_GreaterThenOrEqual: result = a.f64_val >= b.f64_val; break;
@@ -153,8 +145,7 @@ compare_values(Token *pos, Token_Kind op, Value a, Value b){
invalid_default_case; invalid_default_case;
} }
}break; }break;
case TYPE_UNTYPED_STRING: CASE_STRING:{
case TYPE_STRING:{
invalid_codepath; invalid_codepath;
}break; }break;
invalid_default_case; invalid_default_case;
@@ -175,9 +166,7 @@ eval_binary(Token *pos, Token_Kind op, Value a, Value b){
Value result = {}; Value result = {};
result.type = a.type; result.type = a.type;
switch(a.type->kind){ switch(a.type->kind){
case TYPE_UNTYPED_INT: CASE_INT:{
case TYPE_S8:case TYPE_S16:case TYPE_S32:case TYPE_S64:
case TYPE_U8:case TYPE_U16:case TYPE_U32:case TYPE_U64:{
switch(op){ switch(op){
case TK_BitXor: bigint_xor(&result.big_int_val, &a.big_int_val, &b.big_int_val); break; case TK_BitXor: bigint_xor(&result.big_int_val, &a.big_int_val, &b.big_int_val); break;
case TK_BitAnd: bigint_and(&result.big_int_val, &a.big_int_val, &b.big_int_val); break; case TK_BitAnd: bigint_and(&result.big_int_val, &a.big_int_val, &b.big_int_val); break;
@@ -192,8 +181,7 @@ eval_binary(Token *pos, Token_Kind op, Value a, Value b){
invalid_default_case; invalid_default_case;
} }
}break; }break;
case TYPE_UNTYPED_BOOL: CASE_BOOL:{
case TYPE_BOOL:{
switch(op){ switch(op){
case TK_And: result.bool_val = a.bool_val && b.bool_val; break; case TK_And: result.bool_val = a.bool_val && b.bool_val; break;
case TK_Or: result.bool_val = a.bool_val || b.bool_val; break; case TK_Or: result.bool_val = a.bool_val || b.bool_val; break;
@@ -203,8 +191,7 @@ eval_binary(Token *pos, Token_Kind op, Value a, Value b){
invalid_default_case; invalid_default_case;
} }
}break; }break;
case TYPE_UNTYPED_FLOAT: CASE_FLOAT:{
case TYPE_F32: case TYPE_F64:{
switch(op){ switch(op){
case TK_Add: result.f64_val = a.f64_val + b.f64_val; break; case TK_Add: result.f64_val = a.f64_val + b.f64_val; break;
case TK_Sub: result.f64_val = a.f64_val - b.f64_val; break; case TK_Sub: result.f64_val = a.f64_val - b.f64_val; break;
@@ -213,8 +200,7 @@ eval_binary(Token *pos, Token_Kind op, Value a, Value b){
invalid_default_case; invalid_default_case;
} }
}break; }break;
case TYPE_UNTYPED_STRING: CASE_STRING:{
case TYPE_STRING:{
invalid_codepath; invalid_codepath;
}break; }break;
invalid_default_case; invalid_default_case;
@@ -225,41 +211,57 @@ eval_binary(Token *pos, Token_Kind op, Value a, Value b){
function Value function Value
eval_unary(Token *pos, Token_Kind op, Value a){ eval_unary(Token *pos, Token_Kind op, Value a){
if(!is_numeric(a.type)) parsing_error(pos, "Constant application of binary %s on values of type %s is not allowed", name(op), docname(a.type));
BigInt result = {}; BigInt result = {};
switch(op){ switch(op){
case TK_Add:{ case TK_Add:{
return a; return a;
} break; } break;
case TK_Sub:{ case TK_Sub:{
if(is_int(a.type)){ switch(a.type->kind){
CASE_INT:{
bigint_negate(&result, &a.big_int_val); bigint_negate(&result, &a.big_int_val);
return value_int(result); return value_int(result);
} else if(is_float(a.type)){ }break;
CASE_FLOAT:{
return value_float(-a.f64_val); return value_float(-a.f64_val);
} else invalid_codepath; }break;
default:goto failure;
}
} break; } break;
case TK_Neg:{ case TK_Neg:{
if(is_int(a.type)){ switch(a.type->kind){
bigint_not(&result, &a.big_int_val, 64, 1); // Invalid CASE_SINT: case TYPE_UNTYPED_INT:{
bigint_not(&result, &a.big_int_val, a.big_int_val.digit_count*64, 1);
return value_int(result); return value_int(result);
} else invalid_codepath; }break;
CASE_UINT:{
bigint_not(&result, &a.big_int_val, a.big_int_val.digit_count*64, 0);
return value_int(result);
}
default:goto failure;
}
} break; } break;
case TK_Not:{ case TK_Not:{
if(is_int(a.type)){ switch(a.type->kind){
if(CMP_EQ == bigint_cmp_zero(&a.big_int_val)){ CASE_INT: {
if(CMP_EQ == bigint_cmp_zero(&a.big_int_val))
return value_bool(1); return value_bool(1);
} else return value_bool(0); return value_bool(0);
} else if(is_float(a.type)){ }break;
CASE_FLOAT:{
return value_bool(!a.f64_val); return value_bool(!a.f64_val);
} else if(is_bool(a.type)){ }break;
CASE_BOOL:{
a.bool_val = !a.bool_val; a.bool_val = !a.bool_val;
return a; return a;
}break;
default:goto failure;
} }
} break; } break;
default: invalid_codepath; default:goto failure;
} }
failure: parsing_error(pos, "Constant application of binary %s on values of type %s is not allowed", name(op), docname(a.type));
invalid_return; invalid_return;
} }
@@ -433,9 +435,11 @@ field_access_string(Ast_Expr *right){
auto a = (Ast_Atom *)right; auto a = (Ast_Atom *)right;
if(a->intern_val == pctx->intern("len"_s)){ if(a->intern_val == pctx->intern("len"_s)){
return operand_lvalue(type_s64); return operand_lvalue(type_s64);
} else if(a->intern_val == pctx->intern("str"_s)){ }
else if(a->intern_val == pctx->intern("str"_s)){
return operand_lvalue(type_pointer(type_u8)); return operand_lvalue(type_pointer(type_u8));
} else invalid_return; }
else invalid_return;
} }
function Operand function Operand

View File

@@ -46,6 +46,13 @@ enum Ast_Resolved_Type_Kind{
TYPE_LAST_NUMERIC = TYPE_BOOL, TYPE_LAST_NUMERIC = TYPE_BOOL,
}; };
#define CASE_SINT case TYPE_S8:case TYPE_S16:case TYPE_S32:case TYPE_S64
#define CASE_UINT case TYPE_U8:case TYPE_U16:case TYPE_U32:case TYPE_U64
#define CASE_INT case TYPE_UNTYPED_INT: CASE_SINT: CASE_UINT
#define CASE_BOOL case TYPE_UNTYPED_BOOL: case TYPE_BOOL
#define CASE_FLOAT case TYPE_UNTYPED_FLOAT: case TYPE_F32: case TYPE_F64
#define CASE_STRING case TYPE_UNTYPED_STRING: case TYPE_STRING
const char *type_names[] = { const char *type_names[] = {
"[Invalid Ast_Resolved_Type]", "[Invalid Ast_Resolved_Type]",
"[Completing]", "[Completing]",