From 7ddc8ba25d5929e8ef69b05fde43c1ef1602e62e Mon Sep 17 00:00:00 2001 From: lisyarus Date: Mon, 5 Jan 2026 00:36:11 +0300 Subject: [PATCH] Add f16 type & literals support in parser, type checker & interpreter --- libs/ast/include/pslang/ast/literal.hpp | 3 ++ libs/ast/source/print.cpp | 6 +++ .../include/pslang/interpreter/value.hpp | 2 + libs/interpreter/source/eval.cpp | 13 +++++- libs/parser/rules/pslang.l | 2 + libs/parser/rules/pslang.y | 8 +++- .../types/include/pslang/types/half_float.hpp | 45 +++++++++++++++++++ libs/types/include/pslang/types/primitive.hpp | 4 ++ libs/types/source/print.cpp | 5 +++ libs/types/source/type.cpp | 2 +- 10 files changed, 87 insertions(+), 3 deletions(-) create mode 100644 libs/types/include/pslang/types/half_float.hpp diff --git a/libs/ast/include/pslang/ast/literal.hpp b/libs/ast/include/pslang/ast/literal.hpp index aeae7d5..33ec472 100644 --- a/libs/ast/include/pslang/ast/literal.hpp +++ b/libs/ast/include/pslang/ast/literal.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include @@ -26,6 +27,7 @@ namespace pslang::ast using i64_literal = primitive_literal_base; using u64_literal = primitive_literal_base; + using f16_literal = primitive_literal_base; using f32_literal = primitive_literal_base; using f64_literal = primitive_literal_base; @@ -39,6 +41,7 @@ namespace pslang::ast u32_literal, i64_literal, u64_literal, + f16_literal, f32_literal, f64_literal >; diff --git a/libs/ast/source/print.cpp b/libs/ast/source/print.cpp index 28408ca..c78a74f 100644 --- a/libs/ast/source/print.cpp +++ b/libs/ast/source/print.cpp @@ -148,6 +148,12 @@ namespace pslang::ast out << "u64 literal { value = " << node.value << " }\n"; } + void apply(f16_literal const & node) + { + put_indent(out, options); + out << "f32 literal { value = " << std::setprecision(3) << node.value.repr << " }\n"; + } + void apply(f32_literal const & node) { put_indent(out, options); diff --git a/libs/interpreter/include/pslang/interpreter/value.hpp b/libs/interpreter/include/pslang/interpreter/value.hpp index 2360b5d..c279288 100644 --- a/libs/interpreter/include/pslang/interpreter/value.hpp +++ b/libs/interpreter/include/pslang/interpreter/value.hpp @@ -34,6 +34,7 @@ namespace pslang::interpreter using i64_value = primitive_value_base; using u64_value = primitive_value_base; + using f16_value = primitive_value_base; using f32_value = primitive_value_base; using f64_value = primitive_value_base; @@ -47,6 +48,7 @@ namespace pslang::interpreter u32_value, i64_value, u64_value, + f16_value, f32_value, f64_value >; diff --git a/libs/interpreter/source/eval.cpp b/libs/interpreter/source/eval.cpp index 7fce78e..ec4d7c4 100644 --- a/libs/interpreter/source/eval.cpp +++ b/libs/interpreter/source/eval.cpp @@ -336,7 +336,18 @@ namespace pslang::interpreter } else if constexpr (!std::is_same_v && !std::is_same_v) { - return primitive_value(primitive_value_base{static_cast(value.value)}); + if constexpr (std::is_same_v) + { + return primitive_value(primitive_value_base{static_cast(value.value.repr)}); + } + else if constexpr (std::is_same_v) + { + return primitive_value(primitive_value_base{{static_cast(value.value)}}); + } + else + { + return primitive_value(primitive_value_base{static_cast(value.value)}); + } } std::ostringstream os; diff --git a/libs/parser/rules/pslang.l b/libs/parser/rules/pslang.l index e7705c7..b6b3cbc 100644 --- a/libs/parser/rules/pslang.l +++ b/libs/parser/rules/pslang.l @@ -46,6 +46,7 @@ i32 { return bp::make_i32(ctx.location); } u32 { return bp::make_u32(ctx.location); } i64 { return bp::make_i64(ctx.location); } u64 { return bp::make_u64(ctx.location); } +f16 { return bp::make_f16(ctx.location); } f32 { return bp::make_f32(ctx.location); } f64 { return bp::make_f64(ctx.location); } @@ -88,6 +89,7 @@ f64 { return bp::make_f64(ctx.location); } [0-9]+ul { return bp::make_lit_u64(yytext, ctx.location); } [0-9]+\.[0-9]+ { return bp::make_lit_f32(yytext, ctx.location); } +[0-9]+\.[0-9]+h { return bp::make_lit_f16(yytext, ctx.location); } [0-9]+\.[0-9]+l { return bp::make_lit_f64(yytext, ctx.location); } '.' { return bp::make_lit_char8(yytext[1], ctx.location); } diff --git a/libs/parser/rules/pslang.y b/libs/parser/rules/pslang.y index 77ea339..17541d2 100644 --- a/libs/parser/rules/pslang.y +++ b/libs/parser/rules/pslang.y @@ -48,7 +48,9 @@ template { T value; #ifdef __clang__ - if constexpr (std::is_floating_point_v) + if constexpr (std::is_same_v) + value = {float(std::atof(str.data()))}; + else if constexpr (std::is_floating_point_v) value = std::atof(str.data()); else if constexpr (std::is_signed_v) value = std::strtoll(str.data(), nullptr, 10); @@ -137,6 +139,7 @@ template %token u32 %token i64 %token u64 +%token f16 %token f32 %token f64 @@ -259,6 +262,7 @@ primitive_type | u32 { $$ = types::u32_type{}; } | i64 { $$ = types::i64_type{}; } | u64 { $$ = types::u64_type{}; } +| f16 { $$ = types::f16_type{}; } | f32 { $$ = types::f32_type{}; } | f64 { $$ = types::f64_type{}; } ; @@ -309,6 +313,7 @@ postfix_expression | u32 lparen comma_separated_expression_list rparen { $$ = ast::function_call{nullptr, std::make_unique(types::u32_type{}), $3, @$}; } | i64 lparen comma_separated_expression_list rparen { $$ = ast::function_call{nullptr, std::make_unique(types::i64_type{}), $3, @$}; } | u64 lparen comma_separated_expression_list rparen { $$ = ast::function_call{nullptr, std::make_unique(types::u64_type{}), $3, @$}; } +| f16 lparen comma_separated_expression_list rparen { $$ = ast::function_call{nullptr, std::make_unique(types::f16_type{}), $3, @$}; } | f32 lparen comma_separated_expression_list rparen { $$ = ast::function_call{nullptr, std::make_unique(types::f32_type{}), $3, @$}; } | f64 lparen comma_separated_expression_list rparen { $$ = ast::function_call{nullptr, std::make_unique(types::f64_type{}), $3, @$}; } ; @@ -341,6 +346,7 @@ literal | lit_u32 { $$ = parse_primitive_literal($1, ctx.location); } | lit_i64 { $$ = parse_primitive_literal($1, ctx.location); } | lit_u64 { $$ = parse_primitive_literal($1, ctx.location); } +| lit_f16 { $$ = parse_primitive_literal($1, ctx.location); } | lit_f32 { $$ = parse_primitive_literal($1, ctx.location); } | lit_f64 { $$ = parse_primitive_literal($1, ctx.location); } | lit_char8 { $$ = ast::u8_literal{static_cast($1), ctx.location}; } diff --git a/libs/types/include/pslang/types/half_float.hpp b/libs/types/include/pslang/types/half_float.hpp new file mode 100644 index 0000000..8b22d30 --- /dev/null +++ b/libs/types/include/pslang/types/half_float.hpp @@ -0,0 +1,45 @@ +#pragma once + +#include + +#include + +namespace pslang::types +{ + + // TODO: actual half-float operations? Maybe C++23 std::float16_t? + + struct half_float + { + float repr = 0.f; + + friend bool operator == (half_float const &, half_float const &) = default; + friend auto operator <=> (half_float const &, half_float const &) = default; + }; + + inline half_float operator - (half_float f) + { + return {-f.repr}; + } + + inline half_float operator + (half_float f1, half_float f2) + { + return {f1.repr + f2.repr}; + } + + inline half_float operator - (half_float f1, half_float f2) + { + return {f1.repr - f2.repr}; + } + + inline half_float operator * (half_float f1, half_float f2) + { + return {f1.repr * f2.repr}; + } + + inline half_float operator / (half_float f1, half_float f2) + { + return {f1.repr / f2.repr}; + } + +} \ No newline at end of file diff --git a/libs/types/include/pslang/types/primitive.hpp b/libs/types/include/pslang/types/primitive.hpp index 3ea7fde..b24876a 100644 --- a/libs/types/include/pslang/types/primitive.hpp +++ b/libs/types/include/pslang/types/primitive.hpp @@ -1,5 +1,7 @@ #pragma once +#include + #include #include @@ -29,6 +31,7 @@ namespace pslang::types using i64_type = primitive_type_base; using u64_type = primitive_type_base; + using f16_type = primitive_type_base; using f32_type = primitive_type_base; using f64_type = primitive_type_base; @@ -42,6 +45,7 @@ namespace pslang::types u32_type, i64_type, u64_type, + f16_type, f32_type, f64_type >; diff --git a/libs/types/source/print.cpp b/libs/types/source/print.cpp index a54bf26..cf1a62c 100644 --- a/libs/types/source/print.cpp +++ b/libs/types/source/print.cpp @@ -64,6 +64,11 @@ namespace pslang::types out << "u64"; } + void apply(f16_type const &) + { + out << "f16"; + } + void apply(f32_type const &) { out << "f32"; diff --git a/libs/types/source/type.cpp b/libs/types/source/type.cpp index e78897d..1d32638 100644 --- a/libs/types/source/type.cpp +++ b/libs/types/source/type.cpp @@ -93,7 +93,7 @@ namespace pslang::types { return std::visit([](primitive_type_base const &) { - return std::is_floating_point_v; + return std::is_floating_point_v || std::is_same_v; }, *ptype); }