Cleanup
This commit is contained in:
190
typecheck.cpp
190
typecheck.cpp
@@ -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,14 +71,41 @@ 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
|
||||
@@ -119,42 +115,37 @@ 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;
|
||||
case TK_LesserThenOrEqual: result = (cmp == CMP_LT) || (cmp == CMP_EQ); break;
|
||||
case TK_GreaterThenOrEqual: result = (cmp == CMP_GT) || (cmp == CMP_EQ); break;
|
||||
case TK_GreaterThen: result = cmp == CMP_GT; break;
|
||||
case TK_LesserThen: result = cmp == CMP_LT; break;
|
||||
case TK_Equals: result = cmp == CMP_EQ; break;
|
||||
case TK_NotEquals: result = cmp != CMP_EQ; break;
|
||||
case TK_GreaterThen: result = cmp == CMP_GT; break;
|
||||
case TK_LesserThen: result = cmp == CMP_LT; break;
|
||||
case TK_Equals: result = cmp == CMP_EQ; break;
|
||||
case TK_NotEquals: result = cmp != CMP_EQ; break;
|
||||
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;
|
||||
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_LesserThenOrEqual: result = a.f64_val <= b.f64_val; break;
|
||||
case TK_GreaterThenOrEqual: result = a.f64_val >= b.f64_val; break;
|
||||
case TK_GreaterThen: result = a.f64_val > b.f64_val; break;
|
||||
case TK_LesserThen: result = a.f64_val < b.f64_val; break;
|
||||
case TK_Equals: result = a.f64_val == b.f64_val; break;
|
||||
case TK_NotEquals: result = a.f64_val != b.f64_val; break;
|
||||
case TK_GreaterThen: result = a.f64_val > b.f64_val; break;
|
||||
case TK_LesserThen: result = a.f64_val < b.f64_val; break;
|
||||
case TK_Equals: result = a.f64_val == b.f64_val; break;
|
||||
case TK_NotEquals: result = a.f64_val != b.f64_val; break;
|
||||
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)){
|
||||
bigint_negate(&result, &a.big_int_val);
|
||||
return value_int(result);
|
||||
} else if(is_float(a.type)){
|
||||
return value_float(-a.f64_val);
|
||||
} else invalid_codepath;
|
||||
} break;
|
||||
case TK_Neg:{
|
||||
if(is_int(a.type)){
|
||||
bigint_not(&result, &a.big_int_val, 64, 1); // Invalid
|
||||
return value_int(result);
|
||||
} else invalid_codepath;
|
||||
} break;
|
||||
case TK_Not:{
|
||||
if(is_int(a.type)){
|
||||
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(!a.f64_val);
|
||||
} else if(is_bool(a.type)){
|
||||
a.bool_val = !a.bool_val;
|
||||
return a;
|
||||
switch(a.type->kind){
|
||||
CASE_INT:{
|
||||
bigint_negate(&result, &a.big_int_val);
|
||||
return value_int(result);
|
||||
}break;
|
||||
CASE_FLOAT:{
|
||||
return value_float(-a.f64_val);
|
||||
}break;
|
||||
default:goto failure;
|
||||
}
|
||||
} break;
|
||||
default: invalid_codepath;
|
||||
case TK_Neg:{
|
||||
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);
|
||||
}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:{
|
||||
switch(a.type->kind){
|
||||
CASE_INT: {
|
||||
if(CMP_EQ == bigint_cmp_zero(&a.big_int_val))
|
||||
return value_bool(1);
|
||||
return value_bool(0);
|
||||
}break;
|
||||
CASE_FLOAT:{
|
||||
return value_bool(!a.f64_val);
|
||||
}break;
|
||||
CASE_BOOL:{
|
||||
a.bool_val = !a.bool_val;
|
||||
return a;
|
||||
}break;
|
||||
default:goto failure;
|
||||
}
|
||||
} break;
|
||||
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
|
||||
|
||||
7
types.h
7
types.h
@@ -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]",
|
||||
|
||||
Reference in New Issue
Block a user