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...@@ -94,7 +94,9 @@ AssignmentExpression : BoolOrExpression AssignmentOperator BoolOrExpression | Bo
9494
95AssignmentOperator : 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) 95AssignmentOperator : 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 | Block97BlockExpression : IfExpression | Block | WhileExpression
98
99WhileExpression : token(While) Expression Block
98100
99BoolOrExpression : BoolAndExpression token(BoolOr) BoolOrExpression | BoolAndExpression101BoolOrExpression : BoolAndExpression token(BoolOr) BoolOrExpression | BoolAndExpression
100102
src/analyze.cpp+15
...@@ -54,6 +54,7 @@ static AstNode *first_executing_node(AstNode *node) {...@@ -54,6 +54,7 @@ static AstNode *first_executing_node(AstNode *node) {
54 case NodeTypeStructField:54 case NodeTypeStructField:
55 case NodeTypeStructValueExpr:55 case NodeTypeStructValueExpr:
56 case NodeTypeStructValueField:56 case NodeTypeStructValueField:
57 case NodeTypeWhileExpr:
57 return node;58 return node;
58 }59 }
59 zig_panic("unreachable");60 zig_panic("unreachable");
...@@ -526,6 +527,7 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import,...@@ -526,6 +527,7 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import,
526 case NodeTypeCastExpr:527 case NodeTypeCastExpr:
527 case NodeTypePrefixOpExpr:528 case NodeTypePrefixOpExpr:
528 case NodeTypeIfExpr:529 case NodeTypeIfExpr:
530 case NodeTypeWhileExpr:
529 case NodeTypeLabel:531 case NodeTypeLabel:
530 case NodeTypeGoto:532 case NodeTypeGoto:
531 case NodeTypeAsmExpr:533 case NodeTypeAsmExpr:
...@@ -593,6 +595,7 @@ static void preview_types(CodeGen *g, ImportTableEntry *import, AstNode *node) {...@@ -593,6 +595,7 @@ static void preview_types(CodeGen *g, ImportTableEntry *import, AstNode *node) {
593 case NodeTypeCastExpr:595 case NodeTypeCastExpr:
594 case NodeTypePrefixOpExpr:596 case NodeTypePrefixOpExpr:
595 case NodeTypeIfExpr:597 case NodeTypeIfExpr:
598 case NodeTypeWhileExpr:
596 case NodeTypeLabel:599 case NodeTypeLabel:
597 case NodeTypeGoto:600 case NodeTypeGoto:
598 case NodeTypeAsmExpr:601 case NodeTypeAsmExpr:
...@@ -1349,6 +1352,14 @@ static TypeTableEntry *analyze_struct_val_expr(CodeGen *g, ImportTableEntry *imp...@@ -1349,6 +1352,14 @@ static TypeTableEntry *analyze_struct_val_expr(CodeGen *g, ImportTableEntry *imp
1349 return type_entry;1352 return type_entry;
1350}1353}
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
1352static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context,1363static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context,
1353 TypeTableEntry *expected_type, AstNode *node)1364 TypeTableEntry *expected_type, AstNode *node)
1354{1365{
...@@ -1625,6 +1636,9 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,...@@ -1625,6 +1636,9 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
1625 }1636 }
1626 break;1637 break;
1627 }1638 }
1639 case NodeTypeWhileExpr:
1640 return_type = analyze_while_expr(g, import, context, expected_type, node);
1641 break;
1628 case NodeTypeStructValueExpr:1642 case NodeTypeStructValueExpr:
1629 return_type = analyze_struct_val_expr(g, import, context, expected_type, node);1643 return_type = analyze_struct_val_expr(g, import, context, expected_type, node);
1630 break;1644 break;
...@@ -1775,6 +1789,7 @@ static void analyze_top_level_declaration(CodeGen *g, ImportTableEntry *import,...@@ -1775,6 +1789,7 @@ static void analyze_top_level_declaration(CodeGen *g, ImportTableEntry *import,
1775 case NodeTypeCastExpr:1789 case NodeTypeCastExpr:
1776 case NodeTypePrefixOpExpr:1790 case NodeTypePrefixOpExpr:
1777 case NodeTypeIfExpr:1791 case NodeTypeIfExpr:
1792 case NodeTypeWhileExpr:
1778 case NodeTypeLabel:1793 case NodeTypeLabel:
1779 case NodeTypeGoto:1794 case NodeTypeGoto:
1780 case NodeTypeAsmExpr:1795 case NodeTypeAsmExpr:
src/codegen.cpp+27
...@@ -1006,6 +1006,31 @@ static LLVMValueRef gen_struct_val_expr(CodeGen *g, AstNode *node) {...@@ -1006,6 +1006,31 @@ static LLVMValueRef gen_struct_val_expr(CodeGen *g, AstNode *node) {
1006 return tmp_struct_ptr;1006 return tmp_struct_ptr;
1007}1007}
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
1009static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) {1034static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) {
1010 switch (node->type) {1035 switch (node->type) {
1011 case NodeTypeBinOpExpr:1036 case NodeTypeBinOpExpr:
...@@ -1067,6 +1092,8 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) {...@@ -1067,6 +1092,8 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) {
1067 return LLVMConstNull(LLVMInt1Type());1092 return LLVMConstNull(LLVMInt1Type());
1068 case NodeTypeIfExpr:1093 case NodeTypeIfExpr:
1069 return gen_if_expr(g, node);1094 return gen_if_expr(g, node);
1095 case NodeTypeWhileExpr:
1096 return gen_while_expr(g, node);
1070 case NodeTypeAsmExpr:1097 case NodeTypeAsmExpr:
1071 return gen_asm_expr(g, node);1098 return gen_asm_expr(g, node);
1072 case NodeTypeNumberLiteral:1099 case NodeTypeNumberLiteral:
src/parser.cpp+35-1
...@@ -116,6 +116,8 @@ const char *node_type_str(NodeType node_type) {...@@ -116,6 +116,8 @@ const char *node_type_str(NodeType node_type) {
116 return "BoolLiteral";116 return "BoolLiteral";
117 case NodeTypeIfExpr:117 case NodeTypeIfExpr:
118 return "IfExpr";118 return "IfExpr";
119 case NodeTypeWhileExpr:
120 return "WhileExpr";
119 case NodeTypeLabel:121 case NodeTypeLabel:
120 return "Label";122 return "Label";
121 case NodeTypeGoto:123 case NodeTypeGoto:
...@@ -323,6 +325,11 @@ void ast_print(AstNode *node, int indent) {...@@ -323,6 +325,11 @@ void ast_print(AstNode *node, int indent) {
323 if (node->data.if_expr.else_node)325 if (node->data.if_expr.else_node)
324 ast_print(node->data.if_expr.else_node, indent + 2);326 ast_print(node->data.if_expr.else_node, indent + 2);
325 break;327 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;
326 case NodeTypeLabel:333 case NodeTypeLabel:
327 fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.label.name));334 fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.label.name));
328 break;335 break;
...@@ -1727,7 +1734,30 @@ static AstNode *ast_parse_bool_or_expr(ParseContext *pc, int *token_index, bool...@@ -1727,7 +1734,30 @@ static AstNode *ast_parse_bool_or_expr(ParseContext *pc, int *token_index, bool
1727}1734}
17281735
1729/*1736/*
1730BlockExpression : IfExpression | Block1737WhileExpression : 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
1731*/1761*/
1732static AstNode *ast_parse_block_expr(ParseContext *pc, int *token_index, bool mandatory) {1762static AstNode *ast_parse_block_expr(ParseContext *pc, int *token_index, bool mandatory) {
1733 Token *token = &pc->tokens->at(*token_index);1763 Token *token = &pc->tokens->at(*token_index);
...@@ -1740,6 +1770,10 @@ static AstNode *ast_parse_block_expr(ParseContext *pc, int *token_index, bool ma...@@ -1740,6 +1770,10 @@ static AstNode *ast_parse_block_expr(ParseContext *pc, int *token_index, bool ma
1740 if (block)1770 if (block)
1741 return block;1771 return block;
17421772
1773 AstNode *while_expr = ast_parse_while_expr(pc, token_index, false);
1774 if (while_expr)
1775 return while_expr;
1776
1743 if (mandatory)1777 if (mandatory)
1744 ast_invalid_token_error(pc, token);1778 ast_invalid_token_error(pc, token);
17451779
src/parser.hpp+7
...@@ -45,6 +45,7 @@ enum NodeType {...@@ -45,6 +45,7 @@ enum NodeType {
45 NodeTypeVoid,45 NodeTypeVoid,
46 NodeTypeBoolLiteral,46 NodeTypeBoolLiteral,
47 NodeTypeIfExpr,47 NodeTypeIfExpr,
48 NodeTypeWhileExpr,
48 NodeTypeLabel,49 NodeTypeLabel,
49 NodeTypeGoto,50 NodeTypeGoto,
50 NodeTypeAsmExpr,51 NodeTypeAsmExpr,
...@@ -220,6 +221,11 @@ struct AstNodeIfExpr {...@@ -220,6 +221,11 @@ struct AstNodeIfExpr {
220 AstNode *else_node; // null, block node, or other if expr node221 AstNode *else_node; // null, block node, or other if expr node
221};222};
222223
224struct AstNodeWhileExpr {
225 AstNode *condition;
226 AstNode *body;
227};
228
223struct AstNodeLabel {229struct AstNodeLabel {
224 Buf name;230 Buf name;
225};231};
...@@ -334,6 +340,7 @@ struct AstNode {...@@ -334,6 +340,7 @@ struct AstNode {
334 AstNodeArrayAccessExpr array_access_expr;340 AstNodeArrayAccessExpr array_access_expr;
335 AstNodeUse use;341 AstNodeUse use;
336 AstNodeIfExpr if_expr;342 AstNodeIfExpr if_expr;
343 AstNodeWhileExpr while_expr;
337 AstNodeLabel label;344 AstNodeLabel label;
338 AstNodeGoto go_to;345 AstNodeGoto go_to;
339 AstNodeAsmExpr asm_expr;346 AstNodeAsmExpr asm_expr;
src/tokenizer.cpp+9
...@@ -233,6 +233,12 @@ static void end_token(Tokenize *t) {...@@ -233,6 +233,12 @@ static void end_token(Tokenize *t) {
233 t->cur_tok->id = TokenIdKeywordAsm;233 t->cur_tok->id = TokenIdKeywordAsm;
234 } else if (mem_eql_str(token_mem, token_len, "struct")) {234 } else if (mem_eql_str(token_mem, token_len, "struct")) {
235 t->cur_tok->id = TokenIdKeywordStruct;235 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;
236 }242 }
237243
238 t->cur_tok = nullptr;244 t->cur_tok = nullptr;
...@@ -955,6 +961,9 @@ static const char * token_name(Token *token) {...@@ -955,6 +961,9 @@ static const char * token_name(Token *token) {
955 case TokenIdKeywordVolatile: return "Volatile";961 case TokenIdKeywordVolatile: return "Volatile";
956 case TokenIdKeywordAsm: return "Asm";962 case TokenIdKeywordAsm: return "Asm";
957 case TokenIdKeywordStruct: return "Struct";963 case TokenIdKeywordStruct: return "Struct";
964 case TokenIdKeywordWhile: return "While";
965 case TokenIdKeywordContinue: return "Continue";
966 case TokenIdKeywordBreak: return "Break";
958 case TokenIdLParen: return "LParen";967 case TokenIdLParen: return "LParen";
959 case TokenIdRParen: return "RParen";968 case TokenIdRParen: return "RParen";
960 case TokenIdComma: return "Comma";969 case TokenIdComma: return "Comma";
src/tokenizer.hpp+3
...@@ -32,6 +32,9 @@ enum TokenId {...@@ -32,6 +32,9 @@ enum TokenId {
32 TokenIdKeywordAsm,32 TokenIdKeywordAsm,
33 TokenIdKeywordVolatile,33 TokenIdKeywordVolatile,
34 TokenIdKeywordStruct,34 TokenIdKeywordStruct,
35 TokenIdKeywordWhile,
36 TokenIdKeywordContinue,
37 TokenIdKeywordBreak,
35 TokenIdLParen,38 TokenIdLParen,
36 TokenIdRParen,39 TokenIdRParen,
37 TokenIdComma,40 TokenIdComma,