aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Kelley <superjoe30@gmail.com>2016-04-20 11:58:01 -0700
committerAndrew Kelley <superjoe30@gmail.com>2016-04-20 11:58:01 -0700
commit6acc354957752e2cfa8d67bdd0e4c3b42f9be3c3 (patch)
treedf6c6511e3ded50d1be9d59940d093a3470b93b4
parenta25307c0a1b45d0c7b83158349fbc57626baf656 (diff)
downloadzig-6acc354957752e2cfa8d67bdd0e4c3b42f9be3c3.tar.gz
zig-6acc354957752e2cfa8d67bdd0e4c3b42f9be3c3.zip
for loop: add ability to get pointer to elem var
see #51
-rw-r--r--doc/langref.md2
-rw-r--r--src/all_types.hpp1
-rw-r--r--src/analyze.cpp9
-rw-r--r--src/codegen.cpp11
-rw-r--r--src/eval.cpp4
-rw-r--r--src/parser.cpp9
-rw-r--r--test/self_hosted.zig16
7 files changed, 46 insertions, 6 deletions
diff --git a/doc/langref.md b/doc/langref.md
index 827188761a..70ac701f90 100644
--- a/doc/langref.md
+++ b/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
diff --git a/src/all_types.hpp b/src/all_types.hpp
index 830b8db31d..af6a40bde9 100644
--- a/src/all_types.hpp
+++ b/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 {
diff --git a/src/analyze.cpp b/src/analyze.cpp
index 083f4bd2cd..7556597726 100644
--- a/src/analyze.cpp
+++ b/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) {
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 65720f6d59..80eb4b2089 100644
--- a/src/codegen.cpp
+++ b/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);
diff --git a/src/eval.cpp b/src/eval.cpp
index 1fa8f4995e..190f271546 100644
--- a/src/eval.cpp
+++ b/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);
diff --git a/src/parser.cpp b/src/parser.cpp
index 37b062e522..29a65521d7 100644
--- a/src/parser.cpp
+++ b/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);
diff --git a/test/self_hosted.zig b/test/self_hosted.zig
index 44e80e631d..e621dbf3f2 100644
--- a/test/self_hosted.zig
+++ b/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;
+ }
+}