mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Fix bug preventing compile time slices from being iterated over with $foreach.
This commit is contained in:
@@ -73,6 +73,7 @@
|
||||
- Change ordering to simplify adding methods to type in conditional modules.
|
||||
- `#foo` style arguments were not type checked when given a type. #1790
|
||||
- Bug when using +++ on value build a slice or array: the rhs cast was not done.
|
||||
- Fix bug preventing compile time slices from being iterated over with `$foreach`.
|
||||
|
||||
### Stdlib changes
|
||||
- Increase BitWriter.write_bits limit up to 32 bits.
|
||||
|
||||
@@ -2672,54 +2672,70 @@ static inline bool sema_analyse_ct_foreach_stmt(SemaContext *context, Ast *state
|
||||
unsigned ct_context = sema_context_push_ct_stack(context);
|
||||
Expr *collection = exprptr(statement->ct_foreach_stmt.expr);
|
||||
if (!sema_analyse_ct_expr(context, collection)) return false;
|
||||
if (!expr_is_const_untyped_list(collection) && !expr_is_const_initializer(collection)
|
||||
&& !expr_is_const_string(collection) && !expr_is_const_bytes(collection))
|
||||
{
|
||||
SEMA_ERROR(collection, "Expected a list to iterate over");
|
||||
goto FAILED;
|
||||
}
|
||||
if (!expr_is_const(collection)) goto FAILED_NO_LIST;
|
||||
unsigned count;
|
||||
ConstInitializer *initializer = NULL;
|
||||
Expr **expressions = NULL;
|
||||
Type *const_list_type = NULL;
|
||||
const char *bytes = NULL;
|
||||
Type *bytes_type;
|
||||
if (expr_is_const_initializer(collection))
|
||||
switch (collection->const_expr.const_kind)
|
||||
{
|
||||
initializer = collection->const_expr.initializer;
|
||||
ConstInitType init_type = initializer->kind;
|
||||
const_list_type = type_flatten(collection->type);
|
||||
if (const_list_type->type_kind == TYPE_ARRAY || const_list_type->type_kind == TYPE_VECTOR)
|
||||
{
|
||||
count = const_list_type->array.len;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Empty list
|
||||
if (init_type == CONST_INIT_ZERO)
|
||||
case CONST_FLOAT:
|
||||
case CONST_INTEGER:
|
||||
case CONST_BOOL:
|
||||
case CONST_ENUM:
|
||||
case CONST_ERR:
|
||||
case CONST_POINTER:
|
||||
case CONST_TYPEID:
|
||||
case CONST_REF:
|
||||
case CONST_MEMBER:
|
||||
goto FAILED_NO_LIST;
|
||||
case CONST_SLICE:
|
||||
if (!collection->const_expr.slice_init)
|
||||
{
|
||||
sema_context_pop_ct_stack(context, ct_context);
|
||||
statement->ast_kind = AST_NOP_STMT;
|
||||
return true;
|
||||
}
|
||||
if (init_type != CONST_INIT_ARRAY_FULL)
|
||||
initializer = collection->const_expr.slice_init;
|
||||
goto INITIALIZER;
|
||||
case CONST_INITIALIZER:
|
||||
initializer = collection->const_expr.initializer;
|
||||
INITIALIZER:;
|
||||
ConstInitType init_type = initializer->kind;
|
||||
const_list_type = type_flatten(collection->type);
|
||||
if (const_list_type->type_kind == TYPE_ARRAY || const_list_type->type_kind == TYPE_VECTOR)
|
||||
{
|
||||
SEMA_ERROR(collection, "Only regular arrays are allowed here.");
|
||||
goto FAILED;
|
||||
count = const_list_type->array.len;
|
||||
}
|
||||
count = vec_size(initializer->init_array_full);
|
||||
}
|
||||
}
|
||||
else if (expr_is_const_untyped_list(collection))
|
||||
{
|
||||
expressions = collection->const_expr.untyped_list;
|
||||
count = vec_size(expressions);
|
||||
}
|
||||
else
|
||||
{
|
||||
bytes = collection->const_expr.bytes.ptr;
|
||||
count = collection->const_expr.bytes.len;
|
||||
bytes_type = type_get_indexed_type(collection->type);
|
||||
else
|
||||
{
|
||||
// Empty list
|
||||
if (init_type == CONST_INIT_ZERO)
|
||||
{
|
||||
sema_context_pop_ct_stack(context, ct_context);
|
||||
statement->ast_kind = AST_NOP_STMT;
|
||||
return true;
|
||||
}
|
||||
if (init_type != CONST_INIT_ARRAY_FULL)
|
||||
{
|
||||
SEMA_ERROR(collection, "Only regular arrays are allowed here.");
|
||||
goto FAILED;
|
||||
}
|
||||
count = vec_size(initializer->init_array_full);
|
||||
}
|
||||
break;
|
||||
case CONST_UNTYPED_LIST:
|
||||
expressions = collection->const_expr.untyped_list;
|
||||
count = vec_size(expressions);
|
||||
break;
|
||||
case CONST_BYTES:
|
||||
case CONST_STRING:
|
||||
bytes = collection->const_expr.bytes.ptr;
|
||||
count = collection->const_expr.bytes.len;
|
||||
bytes_type = type_get_indexed_type(collection->type);
|
||||
break;
|
||||
}
|
||||
Decl *index = declptrzero(statement->ct_foreach_stmt.index);
|
||||
|
||||
@@ -2771,6 +2787,9 @@ static inline bool sema_analyse_ct_foreach_stmt(SemaContext *context, Ast *state
|
||||
statement->ast_kind = AST_COMPOUND_STMT;
|
||||
statement->compound_stmt = (AstCompoundStmt) { .first_stmt = start };
|
||||
return true;
|
||||
FAILED_NO_LIST:
|
||||
SEMA_ERROR(collection, "Expected a list to iterate over, but this was a non-list expression of type %s.",
|
||||
type_quoted_error_string(collection->type));
|
||||
FAILED:
|
||||
sema_context_pop_ct_stack(context, ct_context);
|
||||
return false;
|
||||
|
||||
@@ -61,6 +61,10 @@ macro Char32[] conv_utf8_to_char32($source) @const
|
||||
import std;
|
||||
fn void main(String[] args)
|
||||
{
|
||||
Char32[] $chars = conv_utf8_to_char32("🐉 eats 🌎");
|
||||
$foreach($v : $chars)
|
||||
io::printn($v);
|
||||
$endforeach
|
||||
Char32[] chars = conv_utf8_to_char32 ("🐉 eats 🌎");
|
||||
io::printn(chars);
|
||||
foreach (c : chars)
|
||||
|
||||
Reference in New Issue
Block a user