authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2015-12-24 14:37:43-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2015-12-24 14:37:43-07:00
loga030b60aebaf6b0e0c07fd5faa1e132ff7e55bbc
treedd904751b8dc721fac9449c1887850b6371b55f1
parent2e74889c3ce61aae8e9e461d1f49a9b5cb79edc2

add while loop


7 files changed, 99 insertions(+), 2 deletions(-)

doc/langref.md+3-1
......@@ -94,7 +94,9 @@ AssignmentExpression : BoolOrExpression AssignmentOperator BoolOrExpression | Bo
9494
9595AssignmentOperator : token(Eq) | token(TimesEq) | token(DivEq) | token(ModEq) | token(PlusEq) | token(MinusEq) | token(BitShiftLeftEq) | token(BitShiftRightEq) | token(BitAndEq) | token(BitXorEq) | token(BitOrEq) | token(BoolAndEq) | token(BoolOrEq)
9696
97BlockExpression : IfExpression | Block
97BlockExpression : IfExpression | Block | WhileExpression
98
99WhileExpression : token(While) Expression Block
98100
99101BoolOrExpression : BoolAndExpression token(BoolOr) BoolOrExpression | BoolAndExpression
100102
src/analyze.cpp+15
......@@ -54,6 +54,7 @@ static AstNode *first_executing_node(AstNode *node) {
5454 case NodeTypeStructField:
5555 case NodeTypeStructValueExpr:
5656 case NodeTypeStructValueField:
57 case NodeTypeWhileExpr:
5758 return node;
5859 }
5960 zig_panic("unreachable");
......@@ -526,6 +527,7 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import,
526527 case NodeTypeCastExpr:
527528 case NodeTypePrefixOpExpr:
528529 case NodeTypeIfExpr:
530 case NodeTypeWhileExpr:
529531 case NodeTypeLabel:
530532 case NodeTypeGoto:
531533 case NodeTypeAsmExpr:
......@@ -593,6 +595,7 @@ static void preview_types(CodeGen *g, ImportTableEntry *import, AstNode *node) {
593595 case NodeTypeCastExpr:
594596 case NodeTypePrefixOpExpr:
595597 case NodeTypeIfExpr:
598 case NodeTypeWhileExpr:
596599 case NodeTypeLabel:
597600 case NodeTypeGoto:
598601 case NodeTypeAsmExpr:
......@@ -1349,6 +1352,14 @@ static TypeTableEntry *analyze_struct_val_expr(CodeGen *g, ImportTableEntry *imp
13491352 return type_entry;
13501353}
13511354
1355static TypeTableEntry *analyze_while_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
1356 TypeTableEntry *expected_type, AstNode *node)
1357{
1358 analyze_expression(g, import, context, g->builtin_types.entry_bool, node->data.while_expr.condition);
1359 analyze_expression(g, import, context, g->builtin_types.entry_void, node->data.while_expr.body);
1360 return g->builtin_types.entry_void;
1361}
1362
13521363static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context,
13531364 TypeTableEntry *expected_type, AstNode *node)
13541365{
......@@ -1625,6 +1636,9 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
16251636 }
16261637 break;
16271638 }
1639 case NodeTypeWhileExpr:
1640 return_type = analyze_while_expr(g, import, context, expected_type, node);
1641 break;
16281642 case NodeTypeStructValueExpr:
16291643 return_type = analyze_struct_val_expr(g, import, context, expected_type, node);
16301644 break;
......@@ -1775,6 +1789,7 @@ static void analyze_top_level_declaration(CodeGen *g, ImportTableEntry *import,
17751789 case NodeTypeCastExpr:
17761790 case NodeTypePrefixOpExpr:
17771791 case NodeTypeIfExpr:
1792 case NodeTypeWhileExpr:
17781793 case NodeTypeLabel:
17791794 case NodeTypeGoto:
17801795 case NodeTypeAsmExpr:
src/codegen.cpp+27
......@@ -1006,6 +1006,31 @@ static LLVMValueRef gen_struct_val_expr(CodeGen *g, AstNode *node) {
10061006 return tmp_struct_ptr;
10071007}
10081008
1009static LLVMValueRef gen_while_expr(CodeGen *g, AstNode *node) {
1010 assert(node->type == NodeTypeWhileExpr);
1011 assert(node->data.while_expr.condition);
1012 assert(node->data.while_expr.body);
1013
1014 LLVMBasicBlockRef cond_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "WhileCond");
1015 LLVMBasicBlockRef body_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "WhileBody");
1016 LLVMBasicBlockRef end_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "WhileEnd");
1017
1018 add_debug_source_node(g, node);
1019 LLVMBuildBr(g->builder, cond_block);
1020
1021 LLVMPositionBuilderAtEnd(g->builder, cond_block);
1022 LLVMValueRef cond_val = gen_expr(g, node->data.while_expr.condition);
1023 add_debug_source_node(g, node->data.while_expr.condition);
1024 LLVMBuildCondBr(g->builder, cond_val, body_block, end_block);
1025
1026 LLVMPositionBuilderAtEnd(g->builder, body_block);
1027 gen_expr(g, node->data.while_expr.body);
1028 LLVMBuildBr(g->builder, cond_block);
1029
1030 LLVMPositionBuilderAtEnd(g->builder, end_block);
1031 return nullptr;
1032}
1033
10091034static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) {
10101035 switch (node->type) {
10111036 case NodeTypeBinOpExpr:
......@@ -1067,6 +1092,8 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) {
10671092 return LLVMConstNull(LLVMInt1Type());
10681093 case NodeTypeIfExpr:
10691094 return gen_if_expr(g, node);
1095 case NodeTypeWhileExpr:
1096 return gen_while_expr(g, node);
10701097 case NodeTypeAsmExpr:
10711098 return gen_asm_expr(g, node);
10721099 case NodeTypeNumberLiteral:
src/parser.cpp+35-1
......@@ -116,6 +116,8 @@ const char *node_type_str(NodeType node_type) {
116116 return "BoolLiteral";
117117 case NodeTypeIfExpr:
118118 return "IfExpr";
119 case NodeTypeWhileExpr:
120 return "WhileExpr";
119121 case NodeTypeLabel:
120122 return "Label";
121123 case NodeTypeGoto:
......@@ -323,6 +325,11 @@ void ast_print(AstNode *node, int indent) {
323325 if (node->data.if_expr.else_node)
324326 ast_print(node->data.if_expr.else_node, indent + 2);
325327 break;
328 case NodeTypeWhileExpr:
329 fprintf(stderr, "%s\n", node_type_str(node->type));
330 ast_print(node->data.while_expr.condition, indent + 2);
331 ast_print(node->data.while_expr.body, indent + 2);
332 break;
326333 case NodeTypeLabel:
327334 fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.label.name));
328335 break;
......@@ -1727,7 +1734,30 @@ static AstNode *ast_parse_bool_or_expr(ParseContext *pc, int *token_index, bool
17271734}
17281735
17291736/*
1730BlockExpression : IfExpression | Block
1737WhileExpression : token(While) Expression Block
1738*/
1739static AstNode *ast_parse_while_expr(ParseContext *pc, int *token_index, bool mandatory) {
1740 Token *token = &pc->tokens->at(*token_index);
1741
1742 if (token->id != TokenIdKeywordWhile) {
1743 if (mandatory) {
1744 ast_invalid_token_error(pc, token);
1745 } else {
1746 return nullptr;
1747 }
1748 }
1749 *token_index += 1;
1750
1751 AstNode *node = ast_create_node(pc, NodeTypeWhileExpr, token);
1752
1753 node->data.while_expr.condition = ast_parse_expression(pc, token_index, true);
1754 node->data.while_expr.body = ast_parse_block(pc, token_index, true);
1755
1756 return node;
1757}
1758
1759/*
1760BlockExpression : IfExpression | Block | WhileExpression
17311761*/
17321762static AstNode *ast_parse_block_expr(ParseContext *pc, int *token_index, bool mandatory) {
17331763 Token *token = &pc->tokens->at(*token_index);
......@@ -1740,6 +1770,10 @@ static AstNode *ast_parse_block_expr(ParseContext *pc, int *token_index, bool ma
17401770 if (block)
17411771 return block;
17421772
1773 AstNode *while_expr = ast_parse_while_expr(pc, token_index, false);
1774 if (while_expr)
1775 return while_expr;
1776
17431777 if (mandatory)
17441778 ast_invalid_token_error(pc, token);
17451779
src/parser.hpp+7
......@@ -45,6 +45,7 @@ enum NodeType {
4545 NodeTypeVoid,
4646 NodeTypeBoolLiteral,
4747 NodeTypeIfExpr,
48 NodeTypeWhileExpr,
4849 NodeTypeLabel,
4950 NodeTypeGoto,
5051 NodeTypeAsmExpr,
......@@ -220,6 +221,11 @@ struct AstNodeIfExpr {
220221 AstNode *else_node; // null, block node, or other if expr node
221222};
222223
224struct AstNodeWhileExpr {
225 AstNode *condition;
226 AstNode *body;
227};
228
223229struct AstNodeLabel {
224230 Buf name;
225231};
......@@ -334,6 +340,7 @@ struct AstNode {
334340 AstNodeArrayAccessExpr array_access_expr;
335341 AstNodeUse use;
336342 AstNodeIfExpr if_expr;
343 AstNodeWhileExpr while_expr;
337344 AstNodeLabel label;
338345 AstNodeGoto go_to;
339346 AstNodeAsmExpr asm_expr;
src/tokenizer.cpp+9
......@@ -233,6 +233,12 @@ static void end_token(Tokenize *t) {
233233 t->cur_tok->id = TokenIdKeywordAsm;
234234 } else if (mem_eql_str(token_mem, token_len, "struct")) {
235235 t->cur_tok->id = TokenIdKeywordStruct;
236 } else if (mem_eql_str(token_mem, token_len, "while")) {
237 t->cur_tok->id = TokenIdKeywordWhile;
238 } else if (mem_eql_str(token_mem, token_len, "continue")) {
239 t->cur_tok->id = TokenIdKeywordContinue;
240 } else if (mem_eql_str(token_mem, token_len, "break")) {
241 t->cur_tok->id = TokenIdKeywordBreak;
236242 }
237243
238244 t->cur_tok = nullptr;
......@@ -955,6 +961,9 @@ static const char * token_name(Token *token) {
955961 case TokenIdKeywordVolatile: return "Volatile";
956962 case TokenIdKeywordAsm: return "Asm";
957963 case TokenIdKeywordStruct: return "Struct";
964 case TokenIdKeywordWhile: return "While";
965 case TokenIdKeywordContinue: return "Continue";
966 case TokenIdKeywordBreak: return "Break";
958967 case TokenIdLParen: return "LParen";
959968 case TokenIdRParen: return "RParen";
960969 case TokenIdComma: return "Comma";
src/tokenizer.hpp+3
......@@ -32,6 +32,9 @@ enum TokenId {
3232 TokenIdKeywordAsm,
3333 TokenIdKeywordVolatile,
3434 TokenIdKeywordStruct,
35 TokenIdKeywordWhile,
36 TokenIdKeywordContinue,
37 TokenIdKeywordBreak,
3538 TokenIdLParen,
3639 TokenIdRParen,
3740 TokenIdComma,