src/onyxastnodes.c
// NOTE: Returns 1 if the conversion was successful.
Returns 1 if the conversion was successful.
Returns 1 if the conversion was successful .
b32 convert_numlit_to_type(AstNumLit* num, Type* type) {
    if (num->type == NULL)
        num->type = type_build_from_ast(semstate.allocator, num->type_node);
    assert(num->type);
    if (types_are_compatible(num->type, type)) return 1;
    if (!type_is_numeric(type)) return 0;
    if (num->type->Basic.kind == Basic_Kind_Int_Unsized) {
          Integer literal auto cast rules:
              - Up in size always works
              - Down in size only works if value is in range of smaller type.
              - Cast to float only works if value is less than the maximum precise value for float size.
        if (type->Basic.flags & Basic_Flag_Integer) {
            if (type->Basic.flags & Basic_Flag_Unsigned) {
                u64 value = (u64) num->value.l;
                if (type->Basic.size == 8) {
                    num->type = type;
                    return 1;
                }
                switch (type->Basic.size) {
                    case 1: if (value <= 255) {
                                num->type = type;
                                return 1;
                            }
                    case 2: if (value <= 65535) {
                                num->type = type;
                                return 1;
                            }
                    case 4: if (value <= 4294967295) {
                                num->type = type;
                                return 1;
                            }
                }
                onyx_report_error(num->token->pos, "Unsigned integer constant with value '%l' does not fit into %d-bits.",
                        num->value.l,
                        type->Basic.size * 8);
            } else {
                i64 value = (i64) num->value.l;
                switch (type->Basic.size) {
                    case 1: if (-128ll <= value && value <= 127ll) {
                                num->value.i = (i32) value;
                                num->type = type;
                                return 1;
                            } break;
                    case 2: if (-32768ll <= value && value <= 32767ll) {
                                num->value.i = (i32) value;
                                num->type = type;
                                return 1;
                            } break;
                    case 4: if (-2147483648ll <= value && value <= 2147483647ll) {
                                num->value.i = (i32) value;
                                num->type = type;
                                return 1;
                            } break;
                    case 8: {   num->type = type;
                                return 1;
                            } break;
                }
                onyx_report_error(num->token->pos, "Integer constant with value '%l' does not fit into %d-bits.",
                        num->value.l,
                        type->Basic.size * 8);
            }
        }
        else if (type->Basic.flags & Basic_Flag_Float) {
            if (type->Basic.size == 4) {
                 TODO(Brendan): Check these boundary conditions
                if (bh_abs(num->value.l) >= (1 << 23)) {
                    onyx_report_error(num->token->pos, "Integer '%l' does not fit in 32-bit float exactly.", num->value.l);
                    return 0;
                }
                num->type = type;
                num->value.f = (f32) num->value.l;
                return 1;
            }
            if (type->Basic.size == 8) {
                 TODO(Brendan): Check these boundary conditions
                if (bh_abs(num->value.l) >= (1ull << 52)) {
                    onyx_report_error(num->token->pos, "Integer '%l' does not fit in 64-bit float exactly.", num->value.l);
                    return 0;
                }
                num->type = type;
                num->value.d = (f64) num->value.l;
                return 1;
            }
        }
    }
    else if (num->type->Basic.kind == Basic_Kind_Float_Unsized) {
         NOTE: Floats don't cast to integers implicitly.
        if ((type->Basic.flags & Basic_Flag_Float) == 0) return 0;
        if (type->Basic.kind == Basic_Kind_F32) {
            num->value.f = (f32) num->value.d;
        }
        num->type = type;
        return 1;
    }
    else if (num->type->Basic.kind == Basic_Kind_F32) {
         NOTE: Floats don't cast to integers implicitly.
        if ((type->Basic.flags & Basic_Flag_Float) == 0) return 0;
        if (type->Basic.kind == Basic_Kind_F64) {
            num->value.d = (f64) num->value.f;
            num->type = type;
            return 1;
        }
    }
    return 0;
}
b32 convert_numlit_to_type ( AstNumLit * num , Type * type ) { if ( num -> type == NULL ) num -> type = type_build_from_ast ( semstate . allocator , num -> type_node ) ; assert ( num -> type ) ; if ( types_are_compatible ( num -> type , type ) ) return 1 ; if ( ! type_is_numeric ( type ) ) return 0 ; if ( num -> type -> Basic . kind == Basic_Kind_Int_Unsized ) { if ( type -> Basic . flags & Basic_Flag_Integer ) { if ( type -> Basic . flags & Basic_Flag_Unsigned ) { u64 value = ( u64 ) num -> value . l ; if ( type -> Basic . size == 8 ) { num -> type = type ; return 1 ; } switch ( type -> Basic . size ) { case 1 : if ( value <= 255 ) { num -> type = type ; return 1 ; } case 2 : if ( value <= 65535 ) { num -> type = type ; return 1 ; } case 4 : if ( value <= 4294967295 ) { num -> type = type ; return 1 ; } } onyx_report_error ( num -> token -> pos , " " , num -> value . l , type -> Basic . size * 8 ) ; } else { i64 value = ( i64 ) num -> value . l ; switch ( type -> Basic . size ) { case 1 : if ( -128ll <= value && value <= 127ll ) { num -> value . i = ( i32 ) value ; num -> type = type ; return 1 ; } break ; case 2 : if ( -32768ll <= value && value <= 32767ll ) { num -> value . i = ( i32 ) value ; num -> type = type ; return 1 ; } break ; case 4 : if ( -2147483648ll <= value && value <= 2147483647ll ) { num -> value . i = ( i32 ) value ; num -> type = type ; return 1 ; } break ; case 8 : { num -> type = type ; return 1 ; } break ; } onyx_report_error ( num -> token -> pos , " " , num -> value . l , type -> Basic . size * 8 ) ; } } else if ( type -> Basic . flags & Basic_Flag_Float ) { if ( type -> Basic . size == 4 ) { if ( bh_abs ( num -> value . l ) >= ( 1 << 23 ) ) { onyx_report_error ( num -> token -> pos , " " , num -> value . l ) ; return 0 ; } num -> type = type ; num -> value . f = ( f32 ) num -> value . l ; return 1 ; } if ( type -> Basic . size == 8 ) { if ( bh_abs ( num -> value . l ) >= ( 1ull << 52 ) ) { onyx_report_error ( num -> token -> pos , " " , num -> value . l ) ; return 0 ; } num -> type = type ; num -> value . d = ( f64 ) num -> value . l ; return 1 ; } } } else if ( num -> type -> Basic . kind == Basic_Kind_Float_Unsized ) { if ( ( type -> Basic . flags & Basic_Flag_Float ) == 0 ) return 0 ; if ( type -> Basic . kind == Basic_Kind_F32 ) { num -> value . f = ( f32 ) num -> value . d ; } num -> type = type ; return 1 ; } else if ( num -> type -> Basic . kind == Basic_Kind_F32 ) { if ( ( type -> Basic . flags & Basic_Flag_Float ) == 0 ) return 0 ; if ( type -> Basic . kind == Basic_Kind_F64 ) { num -> value . d = ( f64 ) num -> value . f ; num -> type = type ; return 1 ; } } return 0 ; }
NOTE: Returns 1 if the conversion was successful.
NOTE : Returns 1 if the conversion was successful .
// //  Integer literal auto cast rules: //      - Up in size always works //      - Down in size only works if value is in range of smaller type. //      - Cast to float only works if value is less than the maximum precise value for float size. // // TODO(Brendan): Check these boundary conditions // TODO(Brendan): Check these boundary conditions // NOTE: Floats don't cast to integers implicitly. // NOTE: Floats don't cast to integers implicitly.