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
//-----------------------------------------------------------------------------
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
value_bool(B32 v){
Value value;
@@ -102,15 +71,42 @@ value_float(BigInt a){
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
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);
}
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);
}
}
function Value
compare_values(Token *pos, Token_Kind op, Value a, Value b){
@@ -119,9 +115,7 @@ compare_values(Token *pos, Token_Kind op, Value a, Value b){
B32 result = 0;
switch(a.type->kind){
case TYPE_UNTYPED_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:{
CASE_INT:{
CmpRes cmp = bigint_cmp(&a.big_int_val, &b.big_int_val);
switch(op){
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;
}
}break;
case TYPE_UNTYPED_BOOL:
case TYPE_BOOL:{
CASE_BOOL:{
switch(op){
case TK_Equals: result = a.bool_val == b.bool_val; break;
case TK_NotEquals: result = a.bool_val != b.bool_val; break;
invalid_default_case;
}
}break;
case TYPE_UNTYPED_FLOAT:
case TYPE_F32: case TYPE_F64:{
CASE_FLOAT:{
switch(op){
case TK_LesserThenOrEqual: 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;
}
}break;
case TYPE_UNTYPED_STRING:
case TYPE_STRING:{
CASE_STRING:{
invalid_codepath;
}break;
invalid_default_case;
@@ -175,9 +166,7 @@ eval_binary(Token *pos, Token_Kind op, Value a, Value b){
Value result = {};
result.type = a.type;
switch(a.type->kind){
case TYPE_UNTYPED_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:{
CASE_INT:{
switch(op){
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;
@@ -192,8 +181,7 @@ eval_binary(Token *pos, Token_Kind op, Value a, Value b){
invalid_default_case;
}
}break;
case TYPE_UNTYPED_BOOL:
case TYPE_BOOL:{
CASE_BOOL:{
switch(op){
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;
@@ -203,8 +191,7 @@ eval_binary(Token *pos, Token_Kind op, Value a, Value b){
invalid_default_case;
}
}break;
case TYPE_UNTYPED_FLOAT:
case TYPE_F32: case TYPE_F64:{
CASE_FLOAT:{
switch(op){
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;
@@ -213,8 +200,7 @@ eval_binary(Token *pos, Token_Kind op, Value a, Value b){
invalid_default_case;
}
}break;
case TYPE_UNTYPED_STRING:
case TYPE_STRING:{
CASE_STRING:{
invalid_codepath;
}break;
invalid_default_case;
@@ -225,41 +211,57 @@ eval_binary(Token *pos, Token_Kind op, Value a, Value b){
function Value
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 = {};
switch(op){
case TK_Add:{
return a;
} break;
case TK_Sub:{
if(is_int(a.type)){
switch(a.type->kind){
CASE_INT:{
bigint_negate(&result, &a.big_int_val);
return value_int(result);
} else if(is_float(a.type)){
}break;
CASE_FLOAT:{
return value_float(-a.f64_val);
} else invalid_codepath;
}break;
default:goto failure;
}
} break;
case TK_Neg:{
if(is_int(a.type)){
bigint_not(&result, &a.big_int_val, 64, 1); // Invalid
switch(a.type->kind){
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);
} 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;
case TK_Not:{
if(is_int(a.type)){
if(CMP_EQ == bigint_cmp_zero(&a.big_int_val)){
switch(a.type->kind){
CASE_INT: {
if(CMP_EQ == bigint_cmp_zero(&a.big_int_val))
return value_bool(1);
} else return value_bool(0);
} else if(is_float(a.type)){
return value_bool(0);
}break;
CASE_FLOAT:{
return value_bool(!a.f64_val);
} else if(is_bool(a.type)){
}break;
CASE_BOOL:{
a.bool_val = !a.bool_val;
return a;
}break;
default:goto failure;
}
} 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;
}
@@ -433,9 +435,11 @@ field_access_string(Ast_Expr *right){
auto a = (Ast_Atom *)right;
if(a->intern_val == pctx->intern("len"_s)){
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));
} else invalid_return;
}
else invalid_return;
}
function Operand

View File

@@ -46,6 +46,13 @@ enum Ast_Resolved_Type_Kind{
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[] = {
"[Invalid Ast_Resolved_Type]",
"[Completing]",