Allow using 'var' to declare lambdas in functions.

This commit is contained in:
Christoffer Lerno
2025-01-01 01:02:35 +01:00
parent 78ff1a4af5
commit 0a809ab5f0
3 changed files with 58 additions and 49 deletions

View File

@@ -14,6 +14,7 @@
- Improve error reporting when using type names as the function argument #1750.
- Improve ordering of method registration to support adding methods to generic modules with method constraints #1746
- Support experimental `@operator(construct)` operator overload.
- Allow using 'var' to declare lambdas in functions.
### Fixes
- Fix case trying to initialize a `char[*]*` from a String.

View File

@@ -4005,60 +4005,60 @@ bool sema_analyse_var_decl(SemaContext *context, Decl *decl, bool local)
SEMA_ERROR(decl, "Constants need to have an initial value.");
return decl_poison(decl);
}
if (kind == VARDECL_LOCAL && !context_is_macro(context))
ASSERT0(!decl->var.no_init);
if (kind == VARDECL_LOCAL && !context_is_macro(context) && init_expr->expr_kind != EXPR_LAMBDA)
{
SEMA_ERROR(decl, "Defining a variable using 'var %s = ...' is only allowed inside a macro.", decl->name);
SEMA_ERROR(decl, "Defining a variable using 'var %s = ...' is only allowed inside a macro, or when defining a lambda.", decl->name);
return decl_poison(decl);
}
ASSERT0(!decl->var.no_init);
if (!type_info)
if (!sema_analyse_expr(context, init_expr)) return decl_poison(decl);
if (global_level_var || !type_is_abi_aggregate(init_expr->type)) sema_cast_const(init_expr);
if (global_level_var && !expr_is_runtime_const(init_expr))
{
if (!sema_analyse_expr(context, init_expr)) return decl_poison(decl);
if (global_level_var || !type_is_abi_aggregate(init_expr->type)) sema_cast_const(init_expr);
if (global_level_var && !expr_is_runtime_const(init_expr))
{
SEMA_ERROR(init_expr, "This expression cannot be evaluated at compile time.");
return decl_poison(decl);
}
decl->type = init_expr->type;
switch (sema_resolve_storage_type(context, init_expr->type))
{
case STORAGE_ERROR:
return decl_poison(decl);
case STORAGE_NORMAL:
break;
case STORAGE_WILDCARD:
SEMA_ERROR(init_expr, "No type can be inferred from the optional result.");
return decl_poison(decl);
case STORAGE_VOID:
SEMA_ERROR(init_expr, "You cannot initialize a value to 'void'.");
return decl_poison(decl);
case STORAGE_COMPILE_TIME:
if (init_expr->type == type_untypedlist)
{
SEMA_ERROR(init_expr, "The type of an untyped list cannot be inferred, you can try adding an explicit type to solve this.");
return decl_poison(decl);
}
if (decl->var.kind == VARDECL_CONST)
{
SEMA_ERROR(init_expr, "You cannot initialize a constant to %s, but you can assign the expression to a compile time variable.", type_invalid_storage_type_name(init_expr->type));
return decl_poison(decl);
}
SEMA_ERROR(init_expr, "You can't store a compile time type in a variable.");
return decl_poison(decl);
case STORAGE_UNKNOWN:
SEMA_ERROR(init_expr, "You cannot initialize a value to %s as it has unknown size.",
type_quoted_error_string(init_expr->type));
return decl_poison(decl);
}
if (!decl->alignment)
{
if (!sema_set_alloca_alignment(context, decl->type, &decl->alignment)) return false;
}
if (!sema_analyse_variable_type(context, decl->type, init_expr->span)) return decl_poison(decl);
// Skip further evaluation.
goto EXIT_OK;
SEMA_ERROR(init_expr, "This expression cannot be evaluated at compile time.");
return decl_poison(decl);
}
decl->type = init_expr->type;
switch (sema_resolve_storage_type(context, init_expr->type))
{
case STORAGE_ERROR:
return decl_poison(decl);
case STORAGE_NORMAL:
break;
case STORAGE_WILDCARD:
SEMA_ERROR(init_expr, "No type can be inferred from the optional result.");
return decl_poison(decl);
case STORAGE_VOID:
SEMA_ERROR(init_expr, "You cannot initialize a value to 'void'.");
return decl_poison(decl);
case STORAGE_COMPILE_TIME:
if (init_expr->type == type_untypedlist)
{
SEMA_ERROR(init_expr,
"The type of an untyped list cannot be inferred, you can try adding an explicit type to solve this.");
return decl_poison(decl);
}
if (decl->var.kind == VARDECL_CONST)
{
SEMA_ERROR(init_expr,
"You cannot initialize a constant to %s, but you can assign the expression to a compile time variable.",
type_invalid_storage_type_name(init_expr->type));
return decl_poison(decl);
}
SEMA_ERROR(init_expr, "You can't store a compile time type in a variable.");
return decl_poison(decl);
case STORAGE_UNKNOWN:
SEMA_ERROR(init_expr, "You cannot initialize a value to %s as it has unknown size.",
type_quoted_error_string(init_expr->type));
return decl_poison(decl);
}
if (!decl->alignment)
{
if (!sema_set_alloca_alignment(context, decl->type, &decl->alignment)) return false;
}
if (!sema_analyse_variable_type(context, decl->type, init_expr->span)) return decl_poison(decl);
// Skip further evaluation.
goto EXIT_OK;
}
if (!sema_resolve_type_info(context, type_info,

View File

@@ -0,0 +1,8 @@
module test;
import std;
fn void main()
{
var x = fn int(int y) { return y * 2; };
io::printn(x(4));
io::printn(x(3));
}