Cleanup
This commit is contained in:
142
typecheck.cpp
142
typecheck.cpp
@@ -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
|
||||||
|
|||||||
7
types.h
7
types.h
@@ -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]",
|
||||||
|
|||||||
Reference in New Issue
Block a user