diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index de5c6b47c..2010634fb 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -1492,6 +1492,8 @@ extern const char *kw_ensure; extern const char *kw_inline; extern const char *kw_kindof; extern const char *kw_len; +extern const char *kw_inf; +extern const char *kw_nan; extern const char *kw_main; extern const char *kw_nameof; extern const char *kw_offsetof; diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 0b8748729..05c6e7431 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -3,7 +3,7 @@ // a copy of which can be found in the LICENSE file. #include "sema_internal.h" - +#include /* * TODOs * - Disallow jumping in and out of an expression block. @@ -1767,6 +1767,7 @@ static inline void expr_rewrite_to_int_const(Expr *expr_to_rewrite, Type *type, expr_to_rewrite->resolve_status = RESOLVE_DONE; } + static inline void expr_rewrite_to_string(Expr *expr_to_rewrite, const char *string) { expr_to_rewrite->expr_kind = EXPR_CONST; @@ -2011,6 +2012,31 @@ static inline bool sema_expr_analyse_type_access(Expr *expr, TypeInfo *parent, b expr_rewrite_to_string(expr, type_generate_qname(canonical)); return true; } + if (type_is_float(canonical)) + { + if (name == kw_nan) + { + expr->expr_kind = EXPR_CONST; + expr->const_expr.kind = canonical->type_kind; + expr->const_expr.f = nanl(""); + expr_set_type(expr, parent->type); + expr->constant = true; + expr->pure = true; + expr->resolve_status = RESOLVE_DONE; + return true; + } + if (name == kw_inf) + { + expr->expr_kind = EXPR_CONST; + expr->const_expr.kind = parent->type->canonical->type_kind; + expr->const_expr.f = HUGE_VALL; + expr_set_type(expr, parent->type->canonical); + expr->constant = true; + expr->pure = true; + expr->resolve_status = RESOLVE_DONE; + return true; + } + } // if (!type_may_have_sub_elements(canonical)) { diff --git a/src/compiler/symtab.c b/src/compiler/symtab.c index 3f780e913..199f04c04 100644 --- a/src/compiler/symtab.c +++ b/src/compiler/symtab.c @@ -42,12 +42,14 @@ const char *kw_distinct; const char *kw_ensure; const char *kw_elements; const char *kw_errors; +const char *kw_inf; const char *kw_inline; const char *kw_kindof; const char *kw_len; const char *kw_main; const char *kw_max; const char *kw_min; +const char *kw_nan; const char *kw_nameof; const char *kw_offsetof; const char *kw_ordinal; @@ -105,6 +107,7 @@ void symtab_init(uint32_t capacity) kw_elements = KW_DEF("elements"); kw_ensure = KW_DEF("ensure"); kw_errors = KW_DEF("errors"); + kw_inf = KW_DEF("inf"); kw_inline = KW_DEF("inline"); kw_kindof = KW_DEF("kindof"); kw_len = KW_DEF("len"); @@ -112,6 +115,7 @@ void symtab_init(uint32_t capacity) kw_max = KW_DEF("max"); kw_min = KW_DEF("min"); kw_nameof = KW_DEF("nameof"); + kw_nan = KW_DEF("nan"); kw_offsetof = KW_DEF("offsetof"); kw_ordinal = KW_DEF("ordinal"); kw_param = KW_DEF("param"); diff --git a/test/test_suite/floats/inf_nan.c3t b/test/test_suite/floats/inf_nan.c3t new file mode 100644 index 000000000..1a024aa61 --- /dev/null +++ b/test/test_suite/floats/inf_nan.c3t @@ -0,0 +1,26 @@ +module fe; + +func void main() +{ + float z = float.inf + 100; + double z2 = double.inf; + float g = float.nan; + double g2 = double.nan; + double x = (double)(z); +} + +// #expect: fe.ll + + %z = alloca float, align 4 + %z2 = alloca double, align 8 + %g = alloca float, align 4 + %g2 = alloca double, align 8 + %x = alloca double, align 8 + store float 0x7FF0000000000000, float* %z, align 4 + store double 0x7FF0000000000000, double* %z2, align 8 + store float 0x7FF8000000000000, float* %g, align 4 + store double 0x7FF8000000000000, double* %g2, align 8 + %0 = load float, float* %z, align 4 + %fpfpext = fpext float %0 to double + store double %fpfpext, double* %x, align 8 + ret void \ No newline at end of file