Commit 6acc354957
Changed files (7)
doc/langref.md
@@ -81,7 +81,7 @@ SwitchItem = Expression | (Expression "..." Expression)
WhileExpression = "while" "(" Expression option(";" Expression) ")" Expression
-ForExpression = "for" "(" Expression ")" option("|" "Symbol" option("," "Symbol") "|") Expression
+ForExpression = "for" "(" Expression ")" option("|" option("*") "Symbol" option("," "Symbol") "|") Expression
BoolOrExpression = BoolAndExpression "||" BoolOrExpression | BoolAndExpression
src/all_types.hpp
@@ -508,6 +508,7 @@ struct AstNodeForExpr {
Expr resolved_expr;
VariableTableEntry *elem_var;
VariableTableEntry *index_var;
+ bool elem_is_ptr;
};
struct AstNodeSwitchExpr {
src/analyze.cpp
@@ -3567,6 +3567,13 @@ static TypeTableEntry *analyze_for_expr(CodeGen *g, ImportTableEntry *import, Bl
child_type = g->builtin_types.entry_invalid;
}
+ TypeTableEntry *var_type;
+ if (node->data.for_expr.elem_is_ptr) {
+ var_type = get_pointer_to_type(g, child_type, false);
+ } else {
+ var_type = child_type;
+ }
+
BlockContext *child_context = new_block_context(node, context);
child_context->parent_loop_node = node;
@@ -3574,7 +3581,7 @@ static TypeTableEntry *analyze_for_expr(CodeGen *g, ImportTableEntry *import, Bl
elem_var_node->block_context = child_context;
Buf *elem_var_name = &elem_var_node->data.symbol_expr.symbol;
node->data.for_expr.elem_var = add_local_var(g, elem_var_node, import, child_context, elem_var_name,
- child_type, true, nullptr);
+ var_type, true, nullptr);
AstNode *index_var_node = node->data.for_expr.index_node;
if (index_var_node) {
src/codegen.cpp
@@ -2427,9 +2427,14 @@ static LLVMValueRef gen_for_expr(CodeGen *g, AstNode *node) {
LLVMPositionBuilderAtEnd(g->builder, body_block);
LLVMValueRef elem_ptr = gen_array_elem_ptr(g, node, array_val, array_type, index_val);
- LLVMValueRef elem_val = handle_is_ptr(child_type) ? elem_ptr : LLVMBuildLoad(g->builder, elem_ptr, "");
- gen_assign_raw(g, node, BinOpTypeAssign, elem_var->value_ref, elem_val,
- elem_var->type, child_type);
+
+ LLVMValueRef elem_val;
+ if (node->data.for_expr.elem_is_ptr) {
+ elem_val = elem_ptr;
+ } else {
+ elem_val = handle_is_ptr(child_type) ? elem_ptr : LLVMBuildLoad(g->builder, elem_ptr, "");
+ }
+ gen_assign_raw(g, node, BinOpTypeAssign, elem_var->value_ref, elem_val, elem_var->type, child_type);
gen_var_debug_decl(g, elem_var);
g->break_block_stack.append(end_block);
g->continue_block_stack.append(continue_block);
src/eval.cpp
@@ -812,6 +812,10 @@ static bool eval_for_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val) {
assert(elem_node->type == NodeTypeSymbol);
Buf *elem_var_name = &elem_node->data.symbol_expr.symbol;
+ if (node->data.for_expr.elem_is_ptr) {
+ zig_panic("TODO");
+ }
+
Buf *index_var_name = nullptr;
if (index_node) {
assert(index_node->type == NodeTypeSymbol);
src/parser.cpp
@@ -1932,7 +1932,7 @@ static AstNode *ast_parse_symbol(ParseContext *pc, int *token_index) {
}
/*
-ForExpression = "for" "(" Expression ")" option("|" "Symbol" option("," "Symbol") "|") Expression
+ForExpression = "for" "(" Expression ")" option("|" option("*") "Symbol" option("," "Symbol") "|") Expression
*/
static AstNode *ast_parse_for_expr(ParseContext *pc, int *token_index, bool mandatory) {
Token *token = &pc->tokens->at(*token_index);
@@ -1955,6 +1955,13 @@ static AstNode *ast_parse_for_expr(ParseContext *pc, int *token_index, bool mand
Token *maybe_bar = &pc->tokens->at(*token_index);
if (maybe_bar->id == TokenIdBinOr) {
*token_index += 1;
+
+ Token *maybe_star = &pc->tokens->at(*token_index);
+ if (maybe_star->id == TokenIdStar) {
+ *token_index += 1;
+ node->data.for_expr.elem_is_ptr = true;
+ }
+
node->data.for_expr.elem_node = ast_parse_symbol(pc, token_index);
Token *maybe_comma = &pc->tokens->at(*token_index);
test/self_hosted.zig
@@ -1269,3 +1269,19 @@ fn while_with_continue_expr() {
}}
assert(sum == 40);
}
+
+
+#attribute("test")
+fn for_loop_with_pointer_elem_var() {
+ const source = "abcdefg";
+ var target: [source.len]u8 = undefined;
+ @memcpy(&target[0], &source[0], source.len);
+ mangle_string(target);
+ assert(str.eql(target, "bcdefgh"));
+}
+#static_eval_enable(false)
+fn mangle_string(s: []u8) {
+ for (s) |*c| {
+ *c += 1;
+ }
+}