authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-04-20 11:58:01-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-04-20 11:58:01-07:00
log6acc354957752e2cfa8d67bdd0e4c3b42f9be3c3
treedf6c6511e3ded50d1be9d59940d093a3470b93b4
parenta25307c0a1b45d0c7b83158349fbc57626baf656

for loop: add ability to get pointer to elem var

see #51

7 files changed, 46 insertions(+), 6 deletions(-)

doc/langref.md+1-1
...@@ -81,7 +81,7 @@ SwitchItem = Expression | (Expression "..." Expression)...@@ -81,7 +81,7 @@ SwitchItem = Expression | (Expression "..." Expression)
8181
82WhileExpression = "while" "(" Expression option(";" Expression) ")" Expression82WhileExpression = "while" "(" Expression option(";" Expression) ")" Expression
8383
84ForExpression = "for" "(" Expression ")" option("|" "Symbol" option("," "Symbol") "|") Expression84ForExpression = "for" "(" Expression ")" option("|" option("*") "Symbol" option("," "Symbol") "|") Expression
8585
86BoolOrExpression = BoolAndExpression "||" BoolOrExpression | BoolAndExpression86BoolOrExpression = BoolAndExpression "||" BoolOrExpression | BoolAndExpression
8787
src/all_types.hpp+1
...@@ -508,6 +508,7 @@ struct AstNodeForExpr {...@@ -508,6 +508,7 @@ struct AstNodeForExpr {
508 Expr resolved_expr;508 Expr resolved_expr;
509 VariableTableEntry *elem_var;509 VariableTableEntry *elem_var;
510 VariableTableEntry *index_var;510 VariableTableEntry *index_var;
511 bool elem_is_ptr;
511};512};
512513
513struct AstNodeSwitchExpr {514struct AstNodeSwitchExpr {
src/analyze.cpp+8-1
...@@ -3567,6 +3567,13 @@ static TypeTableEntry *analyze_for_expr(CodeGen *g, ImportTableEntry *import, Bl...@@ -3567,6 +3567,13 @@ static TypeTableEntry *analyze_for_expr(CodeGen *g, ImportTableEntry *import, Bl
3567 child_type = g->builtin_types.entry_invalid;3567 child_type = g->builtin_types.entry_invalid;
3568 }3568 }
35693569
3570 TypeTableEntry *var_type;
3571 if (node->data.for_expr.elem_is_ptr) {
3572 var_type = get_pointer_to_type(g, child_type, false);
3573 } else {
3574 var_type = child_type;
3575 }
3576
3570 BlockContext *child_context = new_block_context(node, context);3577 BlockContext *child_context = new_block_context(node, context);
3571 child_context->parent_loop_node = node;3578 child_context->parent_loop_node = node;
35723579
...@@ -3574,7 +3581,7 @@ static TypeTableEntry *analyze_for_expr(CodeGen *g, ImportTableEntry *import, Bl...@@ -3574,7 +3581,7 @@ static TypeTableEntry *analyze_for_expr(CodeGen *g, ImportTableEntry *import, Bl
3574 elem_var_node->block_context = child_context;3581 elem_var_node->block_context = child_context;
3575 Buf *elem_var_name = &elem_var_node->data.symbol_expr.symbol;3582 Buf *elem_var_name = &elem_var_node->data.symbol_expr.symbol;
3576 node->data.for_expr.elem_var = add_local_var(g, elem_var_node, import, child_context, elem_var_name,3583 node->data.for_expr.elem_var = add_local_var(g, elem_var_node, import, child_context, elem_var_name,
3577 child_type, true, nullptr);3584 var_type, true, nullptr);
35783585
3579 AstNode *index_var_node = node->data.for_expr.index_node;3586 AstNode *index_var_node = node->data.for_expr.index_node;
3580 if (index_var_node) {3587 if (index_var_node) {
src/codegen.cpp+8-3
...@@ -2427,9 +2427,14 @@ static LLVMValueRef gen_for_expr(CodeGen *g, AstNode *node) {...@@ -2427,9 +2427,14 @@ static LLVMValueRef gen_for_expr(CodeGen *g, AstNode *node) {
24272427
2428 LLVMPositionBuilderAtEnd(g->builder, body_block);2428 LLVMPositionBuilderAtEnd(g->builder, body_block);
2429 LLVMValueRef elem_ptr = gen_array_elem_ptr(g, node, array_val, array_type, index_val);2429 LLVMValueRef elem_ptr = gen_array_elem_ptr(g, node, array_val, array_type, index_val);
2430 LLVMValueRef elem_val = handle_is_ptr(child_type) ? elem_ptr : LLVMBuildLoad(g->builder, elem_ptr, "");2430
2431 gen_assign_raw(g, node, BinOpTypeAssign, elem_var->value_ref, elem_val,2431 LLVMValueRef elem_val;
2432 elem_var->type, child_type);2432 if (node->data.for_expr.elem_is_ptr) {
2433 elem_val = elem_ptr;
2434 } else {
2435 elem_val = handle_is_ptr(child_type) ? elem_ptr : LLVMBuildLoad(g->builder, elem_ptr, "");
2436 }
2437 gen_assign_raw(g, node, BinOpTypeAssign, elem_var->value_ref, elem_val, elem_var->type, child_type);
2433 gen_var_debug_decl(g, elem_var);2438 gen_var_debug_decl(g, elem_var);
2434 g->break_block_stack.append(end_block);2439 g->break_block_stack.append(end_block);
2435 g->continue_block_stack.append(continue_block);2440 g->continue_block_stack.append(continue_block);
src/eval.cpp+4
...@@ -812,6 +812,10 @@ static bool eval_for_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val) {...@@ -812,6 +812,10 @@ static bool eval_for_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val) {
812 assert(elem_node->type == NodeTypeSymbol);812 assert(elem_node->type == NodeTypeSymbol);
813 Buf *elem_var_name = &elem_node->data.symbol_expr.symbol;813 Buf *elem_var_name = &elem_node->data.symbol_expr.symbol;
814814
815 if (node->data.for_expr.elem_is_ptr) {
816 zig_panic("TODO");
817 }
818
815 Buf *index_var_name = nullptr;819 Buf *index_var_name = nullptr;
816 if (index_node) {820 if (index_node) {
817 assert(index_node->type == NodeTypeSymbol);821 assert(index_node->type == NodeTypeSymbol);
src/parser.cpp+8-1
...@@ -1932,7 +1932,7 @@ static AstNode *ast_parse_symbol(ParseContext *pc, int *token_index) {...@@ -1932,7 +1932,7 @@ static AstNode *ast_parse_symbol(ParseContext *pc, int *token_index) {
1932}1932}
19331933
1934/*1934/*
1935ForExpression = "for" "(" Expression ")" option("|" "Symbol" option("," "Symbol") "|") Expression1935ForExpression = "for" "(" Expression ")" option("|" option("*") "Symbol" option("," "Symbol") "|") Expression
1936*/1936*/
1937static AstNode *ast_parse_for_expr(ParseContext *pc, int *token_index, bool mandatory) {1937static AstNode *ast_parse_for_expr(ParseContext *pc, int *token_index, bool mandatory) {
1938 Token *token = &pc->tokens->at(*token_index);1938 Token *token = &pc->tokens->at(*token_index);
...@@ -1955,6 +1955,13 @@ static AstNode *ast_parse_for_expr(ParseContext *pc, int *token_index, bool mand...@@ -1955,6 +1955,13 @@ static AstNode *ast_parse_for_expr(ParseContext *pc, int *token_index, bool mand
1955 Token *maybe_bar = &pc->tokens->at(*token_index);1955 Token *maybe_bar = &pc->tokens->at(*token_index);
1956 if (maybe_bar->id == TokenIdBinOr) {1956 if (maybe_bar->id == TokenIdBinOr) {
1957 *token_index += 1;1957 *token_index += 1;
1958
1959 Token *maybe_star = &pc->tokens->at(*token_index);
1960 if (maybe_star->id == TokenIdStar) {
1961 *token_index += 1;
1962 node->data.for_expr.elem_is_ptr = true;
1963 }
1964
1958 node->data.for_expr.elem_node = ast_parse_symbol(pc, token_index);1965 node->data.for_expr.elem_node = ast_parse_symbol(pc, token_index);
19591966
1960 Token *maybe_comma = &pc->tokens->at(*token_index);1967 Token *maybe_comma = &pc->tokens->at(*token_index);
test/self_hosted.zig+16
...@@ -1269,3 +1269,19 @@ fn while_with_continue_expr() {...@@ -1269,3 +1269,19 @@ fn while_with_continue_expr() {
1269 }}1269 }}
1270 assert(sum == 40);1270 assert(sum == 40);
1271}1271}
1272
1273
1274#attribute("test")
1275fn for_loop_with_pointer_elem_var() {
1276 const source = "abcdefg";
1277 var target: [source.len]u8 = undefined;
1278 @memcpy(&target[0], &source[0], source.len);
1279 mangle_string(target);
1280 assert(str.eql(target, "bcdefgh"));
1281}
1282#static_eval_enable(false)
1283fn mangle_string(s: []u8) {
1284 for (s) |*c| {
1285 *c += 1;
1286 }
1287}