From b313bec69d2f06567fefbdf911563c81407d025c Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Fri, 22 Jul 2022 17:04:30 +0200 Subject: [PATCH] Fix to "typeid.kind". Conversion unsigned int -> enum fixed. @autoimport -> @builtin. Comparison macros. Bump to 0.2.21 --- lib/std/core/builtin.c3 | 14 +++-- lib/std/core/builtin_comparison.c3 | 76 +++++++++++++++++++++++ lib/std/core/types.c3 | 43 +++++++++++++ lib/std/math.c3 | 4 +- lib/std/priorityqueue.c3 | 20 ------ src/compiler/enums.h | 2 +- src/compiler/sema_casts.c | 1 + src/compiler/sema_decls.c | 4 +- src/compiler/sema_expr.c | 9 ++- src/compiler/symtab.c | 2 +- src/version.h | 2 +- test/test_suite/import/autoimport.c3 | 4 +- test/test_suite/stdlib/priorityqueue.c3t | 32 ++++++++++ test/test_suite2/import/autoimport.c3 | 4 +- test/test_suite2/stdlib/priorityqueue.c3t | 32 ++++++++++ 15 files changed, 210 insertions(+), 39 deletions(-) create mode 100644 lib/std/core/builtin_comparison.c3 create mode 100644 test/test_suite/stdlib/priorityqueue.c3t create mode 100644 test/test_suite2/stdlib/priorityqueue.c3t diff --git a/lib/std/core/builtin.c3 b/lib/std/core/builtin.c3 index 378866f79..cd81c7299 100644 --- a/lib/std/core/builtin.c3 +++ b/lib/std/core/builtin.c3 @@ -1,4 +1,4 @@ -// Copyright (c) 2021 Christoffer Lerno. All rights reserved. +// Copyright (c) 2021-2022 Christoffer Lerno and contributors. All rights reserved. // Use of this source code is governed by the MIT license // a copy of which can be found in the LICENSE_STDLIB file. module std::core::builtin; @@ -20,14 +20,14 @@ fault VarCastResult * * @param variable `the variable to store and restore` **/ -macro void @scope(&variable; @body) @autoimport +macro void @scope(&variable; @body) @builtin { $typeof(variable) temp = variable; defer variable = temp; @body(); } -macro void @swap(&a, &b) @autoimport +macro void @swap(&a, &b) @builtin { $typeof(a) temp = a; a = b; @@ -41,7 +41,7 @@ macro void @swap(&a, &b) @autoimport * @param $Type `the type to convert to` * @return `The variant.ptr converted to its type.` **/ -macro varcast(variant v, $Type) @autoimport +macro varcast(variant v, $Type) @builtin { if (v.type != $Type.typeid) return VarCastResult.TYPE_MISMATCH!; return ($Type*)v.ptr; @@ -56,7 +56,7 @@ struct CallstackElement char* file; uint line; } -fn void panic(char* message, char *file, char *function, uint line) @autoimport +fn void panic(char* message, char *file, char *function, uint line) @builtin { CallstackElement* stack = $$stacktrace(); $if ($defined(libc::stderr) && $defined(libc::fprintf)): @@ -82,12 +82,14 @@ fn void panic(char* message, char *file, char *function, uint line) @autoimport $$trap(); } -macro unreachable($string = "Unreachable statement reached.") @autoimport @noreturn +macro unreachable($string = "Unreachable statement reached.") @builtin @noreturn { panic($string, $$FILE, $$FUNC, $$LINE); $$unreachable(); } + + /* enum TypeKind { diff --git a/lib/std/core/builtin_comparison.c3 b/lib/std/core/builtin_comparison.c3 new file mode 100644 index 000000000..0ea6e9824 --- /dev/null +++ b/lib/std/core/builtin_comparison.c3 @@ -0,0 +1,76 @@ +// Copyright (c) 2021-2022 Christoffer Lerno and contributors. All rights reserved. +// Use of this source code is governed by the MIT license +// a copy of which can be found in the LICENSE_STDLIB file. +module std::core::builtin; + +/** + * @require is_comparable_value(a) && is_comparable_value(b) + **/ +macro less(a, b) @builtin +{ + $if ($defined(a.less)): + return a.less(b); + $elif ($defined(a.compare_to)): + return a.compare_to(b) < 0; + $else: + return a < b; + $endif; +} + +/** + * @require is_comparable_value(a) && is_comparable_value(b) + **/ +macro less_eq(a, b) @builtin +{ + $if ($defined(a.less)): + return !b.less(a); + $elif ($defined(a.compare_to)): + return a.compare_to(b) <= 0; + $else: + return a <= b; + $endif; +} + +/** + * @require is_comparable_value(a) && is_comparable_value(b) + **/ +macro greater(a, b) @builtin +{ + $if ($defined(a.less)): + return b.less(a); + $elif ($defined(a.compare_to)): + return a.compare_to(b) > 0; + $else: + return a > b; + $endif; +} + +/** + * @require is_comparable_value(a) && is_comparable_value(b) + **/ +macro greater_eq(a, b) @builtin +{ + $if ($defined(a.less)): + return !a.less(b); + $elif ($defined(a.compare_to)): + return a.compare_to(b) >= 0; + $else: + return a >= b; + $endif; +} + +/** + * @require is_equatable_value(a) && is_equatable_value(b) `values must be equatable` + **/ +macro bool equals(a, b) @builtin +{ + $if ($defined(a.equals)): + return a.equals(b); + $elif ($defined(a.compare_to)): + return a.compare_to(b) == 0; + $elif ($defined(a.less)): + return !a.less(b) && !b.less(a); + $else: + return a == b; + $endif; +} diff --git a/lib/std/core/types.c3 b/lib/std/core/types.c3 index 917962f3f..08c51e8b8 100644 --- a/lib/std/core/types.c3 +++ b/lib/std/core/types.c3 @@ -77,6 +77,49 @@ macro variant_to_int(variant v, $Type) } } +macro bool is_numerical($Type) +{ + var $kind = $Type.typeid.kind; + $if ($kind == TypeKind.DISTINCT): + return is_numerical($Type.typeid.inner); + $else: + return $kind == TypeKind.SIGNED_INT || $kind == TypeKind.UNSIGNED_INT || $kind == TypeKind.FLOAT + || $kind == TypeKind.VECTOR; + $endif; +} + +macro bool is_comparable($Type) +{ + var $kind = $Type.typeid.kind; + $if ($kind == TypeKind.DISTINCT): + return is_comparable($Type.typeid.inner); + $else: + return $kind == TypeKind.SIGNED_INT || $kind == TypeKind.UNSIGNED_INT || $kind == TypeKind.FLOAT + || $kind == TypeKind.VECTOR || $kind == TypeKind.BOOL || $kind == TypeKind.POINTER + || $kind == TypeKind.ENUM; + $endif; +} + +macro bool is_equatable_value(value) +{ + $if ($defined(value.less) || $defined(value.compare_to) || $defined(value.equals)): + return true; + $else: + return is_comparable($typeof(value)); + $endif; +} + +macro bool is_comparable_value(value) +{ + $if ($defined(value.less) || $defined(value.compare_to)): + return true; + $else: + return is_comparable($typeof(value)); + $endif; +} + + + enum TypeKind : char { VOID, diff --git a/lib/std/math.c3 b/lib/std/math.c3 index 35173cd53..fd9666846 100644 --- a/lib/std/math.c3 +++ b/lib/std/math.c3 @@ -67,12 +67,12 @@ const QUAD_MIN_EXP = -16481; const QUAD_EPSILON = 1.92592994438723585305597794258492732e-34; */ -macro max(x, y) @autoimport +macro max(x, y) @builtin { return x > y ? x : y; } -macro min(x, y) @autoimport +macro min(x, y) @builtin { return x < y ? x : y; } diff --git a/lib/std/priorityqueue.c3 b/lib/std/priorityqueue.c3 index c630c1e68..50ef511ef 100644 --- a/lib/std/priorityqueue.c3 +++ b/lib/std/priorityqueue.c3 @@ -23,26 +23,6 @@ module std::priorityqueue; import std::array::list; - -// Helper macros to allow arbitrary non-primitive types to be comparable -private macro bool less(Type x, Type y) -{ - $if ($defined(Type.less)): - return x.less(y); - $else: - return x < y; - $endif; -} - -private macro bool greater(Type x, Type y) -{ - $if ($defined(Type.greater)): - return x.greater(y); - $else: - return x > y; - $endif; -} - define Heap = List; struct PriorityQueue diff --git a/src/compiler/enums.h b/src/compiler/enums.h index 979c8e807..3070a6194 100644 --- a/src/compiler/enums.h +++ b/src/compiler/enums.h @@ -699,7 +699,7 @@ typedef enum ATTRIBUTE_REGCALL, ATTRIBUTE_FASTCALL, ATTRIBUTE_OVERLAP, - ATTRIBUTE_AUTOIMPORT, + ATTRIBUTE_BUILTIN, ATTRIBUTE_OPERATOR, ATTRIBUTE_PURE, ATTRIBUTE_REFLECT, diff --git a/src/compiler/sema_casts.c b/src/compiler/sema_casts.c index b049ce951..e26ee5e4b 100644 --- a/src/compiler/sema_casts.c +++ b/src/compiler/sema_casts.c @@ -1287,6 +1287,7 @@ static bool cast_inner(Expr *expr, Type *from_type, Type *to, Type *to_type) if (type_is_float(to)) return int_to_float(expr, CAST_UIFP, to, to_type); if (to == type_bool) return integer_to_bool(expr, to_type); if (to->type_kind == TYPE_POINTER) return int_to_pointer(expr, to_type); + if (to->type_kind == TYPE_ENUM) return lit_integer_to_enum(expr, to, to_type); break; case ALL_FLOATS: if (type_is_integer(to)) return float_to_integer(expr, to, to_type); diff --git a/src/compiler/sema_decls.c b/src/compiler/sema_decls.c index 58767b6d3..a706d1b8d 100644 --- a/src/compiler/sema_decls.c +++ b/src/compiler/sema_decls.c @@ -1183,7 +1183,7 @@ static bool sema_analyse_attribute(SemaContext *context, Decl *decl, Attr *attr, [ATTRIBUTE_REGCALL] = ATTR_FUNC, [ATTRIBUTE_FASTCALL] = ATTR_FUNC, [ATTRIBUTE_OVERLAP] = ATTR_BITSTRUCT, - [ATTRIBUTE_AUTOIMPORT] = ATTR_MACRO | ATTR_FUNC, + [ATTRIBUTE_BUILTIN] = ATTR_MACRO | ATTR_FUNC, [ATTRIBUTE_OPERATOR] = ATTR_MACRO | ATTR_FUNC, [ATTRIBUTE_REFLECT] = ATTR_ENUM, [ATTRIBUTE_PURE] = ATTR_CALL, @@ -1385,7 +1385,7 @@ static bool sema_analyse_attribute(SemaContext *context, Decl *decl, Attr *attr, assert(domain == ATTR_FUNC); decl->func_decl.attr_naked = true; break; - case ATTRIBUTE_AUTOIMPORT: + case ATTRIBUTE_BUILTIN: decl->is_autoimport = true; break; case ATTRIBUTE_OVERLAP: diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index d4eb054fc..00b248250 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -3427,7 +3427,9 @@ static inline void sema_rewrite_typeid_kind(Expr *expr, Expr *parent, Expr *curr if (current_parent->expr_kind == EXPR_CONST) { unsigned val = type_get_introspection_kind(current_parent->const_expr.typeid->type_kind); - expr_rewrite_to_int_const(expr, type_for_kind, val, false); + assert(type_for_kind->type_kind == TYPE_ENUM); + expr_rewrite_to_int_const(expr, type_flatten(type_for_kind), val, false); + cast(expr, type_for_kind); return; } expr->expr_kind = EXPR_TYPEID_INFO; @@ -3450,6 +3452,9 @@ static inline bool sema_rewrite_typeid_inner(Expr *expr, Expr *parent, Expr *cur case TYPE_FAILABLE: inner = type->failable; break; + case TYPE_DISTINCT: + inner = type->decl->distinct_decl.base_type->canonical; + break; case TYPE_ARRAY: case TYPE_FLEXIBLE_ARRAY: case TYPE_SUBARRAY: @@ -3463,7 +3468,7 @@ static inline bool sema_rewrite_typeid_inner(Expr *expr, Expr *parent, Expr *cur } if (!inner) { - SEMA_ERROR(expr, "Cannot access 'inner' of non pointer/array type %s.", type_quoted_error_string(current_parent->const_expr.typeid)); + SEMA_ERROR(expr, "Cannot %s does not have a property 'inner'.", type_quoted_error_string(current_parent->const_expr.typeid)); return false; } expr_replace(expr, current_parent); diff --git a/src/compiler/symtab.c b/src/compiler/symtab.c index 5ea6f222c..16a4126ec 100644 --- a/src/compiler/symtab.c +++ b/src/compiler/symtab.c @@ -229,7 +229,7 @@ void symtab_init(uint32_t capacity) attribute_list[ATTRIBUTE_OPERATOR] = KW_DEF("@operator"); attribute_list[ATTRIBUTE_PURE] = kw_at_pure; attribute_list[ATTRIBUTE_REFLECT] = KW_DEF("@reflect"); - attribute_list[ATTRIBUTE_AUTOIMPORT] = KW_DEF("@autoimport"); + attribute_list[ATTRIBUTE_BUILTIN] = KW_DEF("@builtin"); attribute_list[ATTRIBUTE_MAYDISCARD] = KW_DEF("@maydiscard"); attribute_list[ATTRIBUTE_NODISCARD] = KW_DEF("@nodiscard"); diff --git a/src/version.h b/src/version.h index 1ba65d899..2a35980c6 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define COMPILER_VERSION "0.2.20" \ No newline at end of file +#define COMPILER_VERSION "0.2.21" \ No newline at end of file diff --git a/test/test_suite/import/autoimport.c3 b/test/test_suite/import/autoimport.c3 index afdfc74de..8b80f199e 100644 --- a/test/test_suite/import/autoimport.c3 +++ b/test/test_suite/import/autoimport.c3 @@ -1,11 +1,11 @@ module foo; -fn int test() @autoimport +fn int test() @builtin { return 1; } -macro int testm() @autoimport +macro int testm() @builtin { return 1; } diff --git a/test/test_suite/stdlib/priorityqueue.c3t b/test/test_suite/stdlib/priorityqueue.c3t new file mode 100644 index 000000000..8ab896035 --- /dev/null +++ b/test/test_suite/stdlib/priorityqueue.c3t @@ -0,0 +1,32 @@ +// #target: macos-x64 +module test; +import std::io; +import std::math; +import std::priorityqueue; + +define FooPriorityQueue = PriorityQueue; + +fn void main() +{ + + FooPriorityQueue agh; + agh.max = true; + agh.push(Foo { 3 }); + agh.push(Foo { 101 }); + agh.push(Foo { 10 }); + while (try f = agh.pop()) io::printf("%s\n", f.x); +} + +struct Foo +{ + int x; +} + +fn bool Foo.less(Foo* x, Foo y) @inline +{ + return x.x < y.x; +} + +// #expect: test.ll + +%PriorityQueue = type { %List, i8 } diff --git a/test/test_suite2/import/autoimport.c3 b/test/test_suite2/import/autoimport.c3 index afdfc74de..8b80f199e 100644 --- a/test/test_suite2/import/autoimport.c3 +++ b/test/test_suite2/import/autoimport.c3 @@ -1,11 +1,11 @@ module foo; -fn int test() @autoimport +fn int test() @builtin { return 1; } -macro int testm() @autoimport +macro int testm() @builtin { return 1; } diff --git a/test/test_suite2/stdlib/priorityqueue.c3t b/test/test_suite2/stdlib/priorityqueue.c3t new file mode 100644 index 000000000..8ab896035 --- /dev/null +++ b/test/test_suite2/stdlib/priorityqueue.c3t @@ -0,0 +1,32 @@ +// #target: macos-x64 +module test; +import std::io; +import std::math; +import std::priorityqueue; + +define FooPriorityQueue = PriorityQueue; + +fn void main() +{ + + FooPriorityQueue agh; + agh.max = true; + agh.push(Foo { 3 }); + agh.push(Foo { 101 }); + agh.push(Foo { 10 }); + while (try f = agh.pop()) io::printf("%s\n", f.x); +} + +struct Foo +{ + int x; +} + +fn bool Foo.less(Foo* x, Foo y) @inline +{ + return x.x < y.x; +} + +// #expect: test.ll + +%PriorityQueue = type { %List, i8 }