From 8b6735a6aa7474c0b253aecc94fbd15d74c85998 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Tue, 16 Apr 2024 19:42:32 +0200 Subject: [PATCH] Allow recursive function definitions as long as they are pointers #1182. Add 'zstr' variants for `string::new_format` / `string::tformat`. --- lib/std/core/string.c3 | 16 ++++++++++++++++ releasenotes.md | 3 ++- src/compiler/parse_global.c | 1 + src/compiler/sema_decls.c | 6 +++--- src/compiler/sema_expr.c | 2 +- .../functions/recursive_through_generic.c3 | 2 +- 6 files changed, 24 insertions(+), 6 deletions(-) diff --git a/lib/std/core/string.c3 b/lib/std/core/string.c3 index 54e553e6f..69664fb73 100644 --- a/lib/std/core/string.c3 +++ b/lib/std/core/string.c3 @@ -38,6 +38,13 @@ macro String tformat(String fmt, ...) return str.str_view(); } +macro ZString tformat_zstr(String fmt, ...) +{ + DString str = dstring::temp_with_capacity(fmt.len + $vacount * 8); + str.appendf(fmt, $vasplat()); + return str.zstr_view(); +} + macro String new_format(String fmt, ..., Allocator* allocator = allocator::heap()) { @pool(allocator) @@ -48,6 +55,15 @@ macro String new_format(String fmt, ..., Allocator* allocator = allocator::heap( }; } +macro ZString new_format_zstr(String fmt, ..., Allocator* allocator = allocator::heap()) +{ + @pool(allocator) + { + DString str = dstring::temp_with_capacity(fmt.len + $vacount * 8); + str.appendf(fmt, $vasplat()); + return str.copy_zstr(allocator); + }; +} macro bool char_in_set(char c, String set) { diff --git a/releasenotes.md b/releasenotes.md index 54b06fbd2..10e51bf0f 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -5,12 +5,13 @@ ### Changes / improvements - Support `defer (catch err)` - Added `print-input` command argument to print all files used for compilation +- Allow recursive function definitions as long as they are pointers. #1182 ### Fixes - Incorrect length passed to scratch buffer printf. ### Stdlib changes -None +- Add 'zstr' variants for `string::new_format` / `string::tformat`. ## 0.5.5 Change list diff --git a/src/compiler/parse_global.c b/src/compiler/parse_global.c index 62b282a63..000cf1bb4 100644 --- a/src/compiler/parse_global.c +++ b/src/compiler/parse_global.c @@ -1831,6 +1831,7 @@ static inline Decl *parse_def_type(ParseContext *c) return poisoned_decl; } if (!parse_attributes_for_global(c, decl)) return poisoned_decl; + RANGE_EXTEND_PREV(decl_type); RANGE_EXTEND_PREV(decl); CONSUME_EOS_OR_RET(poisoned_decl); return decl; diff --git a/src/compiler/sema_decls.c b/src/compiler/sema_decls.c index d7e3d920b..6eb78f556 100644 --- a/src/compiler/sema_decls.c +++ b/src/compiler/sema_decls.c @@ -914,7 +914,7 @@ static inline bool sema_analyse_signature(SemaContext *context, Signature *sig, return false; } } - if (!sema_resolve_type_structure(context, rtype_info->type, rtype_info->span)) return false; + if (type_is_func_ptr(rtype_info->type) && !sema_resolve_type_structure(context, rtype_info->type, rtype_info->span)) return false; } // We don't support more than MAX_PARAMS number of params. This makes everything sane. @@ -1092,8 +1092,8 @@ static inline bool sema_analyse_signature(SemaContext *context, Signature *sig, if (type_info) { - if (!sema_resolve_type_structure(context, type_info->type, type_info->span)) return false; - + Type *type = type_info->type; + if (type_is_func_ptr(type) && !sema_resolve_type_structure(context, type, type_info->span)) return false; param->type = type_info->type; if (!sema_set_abi_alignment(context, param->type, ¶m->alignment)) return false; } diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 951052618..96abbf10c 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -7574,7 +7574,7 @@ static inline bool sema_expr_analyse_lambda(SemaContext *context, Type *target_t { if (!type_is_func_ptr(flat)) { - SEMA_ERROR(expr, "Can't convert a lambda to %s.", type_quoted_error_string(target_type)); + RETURN_SEMA_ERROR(expr, "Can't convert a lambda to %s.", type_quoted_error_string(target_type)); } if (!sema_resolve_type_decl(context, flat->pointer)) return false; } diff --git a/test/test_suite/functions/recursive_through_generic.c3 b/test/test_suite/functions/recursive_through_generic.c3 index 1b250e547..919fac100 100644 --- a/test/test_suite/functions/recursive_through_generic.c3 +++ b/test/test_suite/functions/recursive_through_generic.c3 @@ -5,7 +5,7 @@ fn void! main() { } -def FooFunc = fn void! (Bar*); // #error: Recursive definition +def FooFunc = fn void! (Bar); // #error: Recursive definition def Foo = HashMap(); struct Bar