add while loop
This commit is contained in:
parent
2e74889c3c
commit
a030b60aeb
@ -94,7 +94,9 @@ AssignmentExpression : BoolOrExpression AssignmentOperator BoolOrExpression | Bo
|
|||||||
|
|
||||||
AssignmentOperator : 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)
|
AssignmentOperator : 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)
|
||||||
|
|
||||||
BlockExpression : IfExpression | Block
|
BlockExpression : IfExpression | Block | WhileExpression
|
||||||
|
|
||||||
|
WhileExpression : token(While) Expression Block
|
||||||
|
|
||||||
BoolOrExpression : BoolAndExpression token(BoolOr) BoolOrExpression | BoolAndExpression
|
BoolOrExpression : BoolAndExpression token(BoolOr) BoolOrExpression | BoolAndExpression
|
||||||
|
|
||||||
|
@ -54,6 +54,7 @@ static AstNode *first_executing_node(AstNode *node) {
|
|||||||
case NodeTypeStructField:
|
case NodeTypeStructField:
|
||||||
case NodeTypeStructValueExpr:
|
case NodeTypeStructValueExpr:
|
||||||
case NodeTypeStructValueField:
|
case NodeTypeStructValueField:
|
||||||
|
case NodeTypeWhileExpr:
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
zig_panic("unreachable");
|
zig_panic("unreachable");
|
||||||
@ -526,6 +527,7 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import,
|
|||||||
case NodeTypeCastExpr:
|
case NodeTypeCastExpr:
|
||||||
case NodeTypePrefixOpExpr:
|
case NodeTypePrefixOpExpr:
|
||||||
case NodeTypeIfExpr:
|
case NodeTypeIfExpr:
|
||||||
|
case NodeTypeWhileExpr:
|
||||||
case NodeTypeLabel:
|
case NodeTypeLabel:
|
||||||
case NodeTypeGoto:
|
case NodeTypeGoto:
|
||||||
case NodeTypeAsmExpr:
|
case NodeTypeAsmExpr:
|
||||||
@ -593,6 +595,7 @@ static void preview_types(CodeGen *g, ImportTableEntry *import, AstNode *node) {
|
|||||||
case NodeTypeCastExpr:
|
case NodeTypeCastExpr:
|
||||||
case NodeTypePrefixOpExpr:
|
case NodeTypePrefixOpExpr:
|
||||||
case NodeTypeIfExpr:
|
case NodeTypeIfExpr:
|
||||||
|
case NodeTypeWhileExpr:
|
||||||
case NodeTypeLabel:
|
case NodeTypeLabel:
|
||||||
case NodeTypeGoto:
|
case NodeTypeGoto:
|
||||||
case NodeTypeAsmExpr:
|
case NodeTypeAsmExpr:
|
||||||
@ -1349,6 +1352,14 @@ static TypeTableEntry *analyze_struct_val_expr(CodeGen *g, ImportTableEntry *imp
|
|||||||
return type_entry;
|
return type_entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static TypeTableEntry *analyze_while_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
|
||||||
|
TypeTableEntry *expected_type, AstNode *node)
|
||||||
|
{
|
||||||
|
analyze_expression(g, import, context, g->builtin_types.entry_bool, node->data.while_expr.condition);
|
||||||
|
analyze_expression(g, import, context, g->builtin_types.entry_void, node->data.while_expr.body);
|
||||||
|
return g->builtin_types.entry_void;
|
||||||
|
}
|
||||||
|
|
||||||
static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context,
|
static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context,
|
||||||
TypeTableEntry *expected_type, AstNode *node)
|
TypeTableEntry *expected_type, AstNode *node)
|
||||||
{
|
{
|
||||||
@ -1625,6 +1636,9 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case NodeTypeWhileExpr:
|
||||||
|
return_type = analyze_while_expr(g, import, context, expected_type, node);
|
||||||
|
break;
|
||||||
case NodeTypeStructValueExpr:
|
case NodeTypeStructValueExpr:
|
||||||
return_type = analyze_struct_val_expr(g, import, context, expected_type, node);
|
return_type = analyze_struct_val_expr(g, import, context, expected_type, node);
|
||||||
break;
|
break;
|
||||||
@ -1775,6 +1789,7 @@ static void analyze_top_level_declaration(CodeGen *g, ImportTableEntry *import,
|
|||||||
case NodeTypeCastExpr:
|
case NodeTypeCastExpr:
|
||||||
case NodeTypePrefixOpExpr:
|
case NodeTypePrefixOpExpr:
|
||||||
case NodeTypeIfExpr:
|
case NodeTypeIfExpr:
|
||||||
|
case NodeTypeWhileExpr:
|
||||||
case NodeTypeLabel:
|
case NodeTypeLabel:
|
||||||
case NodeTypeGoto:
|
case NodeTypeGoto:
|
||||||
case NodeTypeAsmExpr:
|
case NodeTypeAsmExpr:
|
||||||
|
@ -1006,6 +1006,31 @@ static LLVMValueRef gen_struct_val_expr(CodeGen *g, AstNode *node) {
|
|||||||
return tmp_struct_ptr;
|
return tmp_struct_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static LLVMValueRef gen_while_expr(CodeGen *g, AstNode *node) {
|
||||||
|
assert(node->type == NodeTypeWhileExpr);
|
||||||
|
assert(node->data.while_expr.condition);
|
||||||
|
assert(node->data.while_expr.body);
|
||||||
|
|
||||||
|
LLVMBasicBlockRef cond_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "WhileCond");
|
||||||
|
LLVMBasicBlockRef body_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "WhileBody");
|
||||||
|
LLVMBasicBlockRef end_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "WhileEnd");
|
||||||
|
|
||||||
|
add_debug_source_node(g, node);
|
||||||
|
LLVMBuildBr(g->builder, cond_block);
|
||||||
|
|
||||||
|
LLVMPositionBuilderAtEnd(g->builder, cond_block);
|
||||||
|
LLVMValueRef cond_val = gen_expr(g, node->data.while_expr.condition);
|
||||||
|
add_debug_source_node(g, node->data.while_expr.condition);
|
||||||
|
LLVMBuildCondBr(g->builder, cond_val, body_block, end_block);
|
||||||
|
|
||||||
|
LLVMPositionBuilderAtEnd(g->builder, body_block);
|
||||||
|
gen_expr(g, node->data.while_expr.body);
|
||||||
|
LLVMBuildBr(g->builder, cond_block);
|
||||||
|
|
||||||
|
LLVMPositionBuilderAtEnd(g->builder, end_block);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) {
|
static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) {
|
||||||
switch (node->type) {
|
switch (node->type) {
|
||||||
case NodeTypeBinOpExpr:
|
case NodeTypeBinOpExpr:
|
||||||
@ -1067,6 +1092,8 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) {
|
|||||||
return LLVMConstNull(LLVMInt1Type());
|
return LLVMConstNull(LLVMInt1Type());
|
||||||
case NodeTypeIfExpr:
|
case NodeTypeIfExpr:
|
||||||
return gen_if_expr(g, node);
|
return gen_if_expr(g, node);
|
||||||
|
case NodeTypeWhileExpr:
|
||||||
|
return gen_while_expr(g, node);
|
||||||
case NodeTypeAsmExpr:
|
case NodeTypeAsmExpr:
|
||||||
return gen_asm_expr(g, node);
|
return gen_asm_expr(g, node);
|
||||||
case NodeTypeNumberLiteral:
|
case NodeTypeNumberLiteral:
|
||||||
|
@ -116,6 +116,8 @@ const char *node_type_str(NodeType node_type) {
|
|||||||
return "BoolLiteral";
|
return "BoolLiteral";
|
||||||
case NodeTypeIfExpr:
|
case NodeTypeIfExpr:
|
||||||
return "IfExpr";
|
return "IfExpr";
|
||||||
|
case NodeTypeWhileExpr:
|
||||||
|
return "WhileExpr";
|
||||||
case NodeTypeLabel:
|
case NodeTypeLabel:
|
||||||
return "Label";
|
return "Label";
|
||||||
case NodeTypeGoto:
|
case NodeTypeGoto:
|
||||||
@ -323,6 +325,11 @@ void ast_print(AstNode *node, int indent) {
|
|||||||
if (node->data.if_expr.else_node)
|
if (node->data.if_expr.else_node)
|
||||||
ast_print(node->data.if_expr.else_node, indent + 2);
|
ast_print(node->data.if_expr.else_node, indent + 2);
|
||||||
break;
|
break;
|
||||||
|
case NodeTypeWhileExpr:
|
||||||
|
fprintf(stderr, "%s\n", node_type_str(node->type));
|
||||||
|
ast_print(node->data.while_expr.condition, indent + 2);
|
||||||
|
ast_print(node->data.while_expr.body, indent + 2);
|
||||||
|
break;
|
||||||
case NodeTypeLabel:
|
case NodeTypeLabel:
|
||||||
fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.label.name));
|
fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.label.name));
|
||||||
break;
|
break;
|
||||||
@ -1727,7 +1734,30 @@ static AstNode *ast_parse_bool_or_expr(ParseContext *pc, int *token_index, bool
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
BlockExpression : IfExpression | Block
|
WhileExpression : token(While) Expression Block
|
||||||
|
*/
|
||||||
|
static AstNode *ast_parse_while_expr(ParseContext *pc, int *token_index, bool mandatory) {
|
||||||
|
Token *token = &pc->tokens->at(*token_index);
|
||||||
|
|
||||||
|
if (token->id != TokenIdKeywordWhile) {
|
||||||
|
if (mandatory) {
|
||||||
|
ast_invalid_token_error(pc, token);
|
||||||
|
} else {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*token_index += 1;
|
||||||
|
|
||||||
|
AstNode *node = ast_create_node(pc, NodeTypeWhileExpr, token);
|
||||||
|
|
||||||
|
node->data.while_expr.condition = ast_parse_expression(pc, token_index, true);
|
||||||
|
node->data.while_expr.body = ast_parse_block(pc, token_index, true);
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
BlockExpression : IfExpression | Block | WhileExpression
|
||||||
*/
|
*/
|
||||||
static AstNode *ast_parse_block_expr(ParseContext *pc, int *token_index, bool mandatory) {
|
static AstNode *ast_parse_block_expr(ParseContext *pc, int *token_index, bool mandatory) {
|
||||||
Token *token = &pc->tokens->at(*token_index);
|
Token *token = &pc->tokens->at(*token_index);
|
||||||
@ -1740,6 +1770,10 @@ static AstNode *ast_parse_block_expr(ParseContext *pc, int *token_index, bool ma
|
|||||||
if (block)
|
if (block)
|
||||||
return block;
|
return block;
|
||||||
|
|
||||||
|
AstNode *while_expr = ast_parse_while_expr(pc, token_index, false);
|
||||||
|
if (while_expr)
|
||||||
|
return while_expr;
|
||||||
|
|
||||||
if (mandatory)
|
if (mandatory)
|
||||||
ast_invalid_token_error(pc, token);
|
ast_invalid_token_error(pc, token);
|
||||||
|
|
||||||
|
@ -45,6 +45,7 @@ enum NodeType {
|
|||||||
NodeTypeVoid,
|
NodeTypeVoid,
|
||||||
NodeTypeBoolLiteral,
|
NodeTypeBoolLiteral,
|
||||||
NodeTypeIfExpr,
|
NodeTypeIfExpr,
|
||||||
|
NodeTypeWhileExpr,
|
||||||
NodeTypeLabel,
|
NodeTypeLabel,
|
||||||
NodeTypeGoto,
|
NodeTypeGoto,
|
||||||
NodeTypeAsmExpr,
|
NodeTypeAsmExpr,
|
||||||
@ -220,6 +221,11 @@ struct AstNodeIfExpr {
|
|||||||
AstNode *else_node; // null, block node, or other if expr node
|
AstNode *else_node; // null, block node, or other if expr node
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct AstNodeWhileExpr {
|
||||||
|
AstNode *condition;
|
||||||
|
AstNode *body;
|
||||||
|
};
|
||||||
|
|
||||||
struct AstNodeLabel {
|
struct AstNodeLabel {
|
||||||
Buf name;
|
Buf name;
|
||||||
};
|
};
|
||||||
@ -334,6 +340,7 @@ struct AstNode {
|
|||||||
AstNodeArrayAccessExpr array_access_expr;
|
AstNodeArrayAccessExpr array_access_expr;
|
||||||
AstNodeUse use;
|
AstNodeUse use;
|
||||||
AstNodeIfExpr if_expr;
|
AstNodeIfExpr if_expr;
|
||||||
|
AstNodeWhileExpr while_expr;
|
||||||
AstNodeLabel label;
|
AstNodeLabel label;
|
||||||
AstNodeGoto go_to;
|
AstNodeGoto go_to;
|
||||||
AstNodeAsmExpr asm_expr;
|
AstNodeAsmExpr asm_expr;
|
||||||
|
@ -233,6 +233,12 @@ static void end_token(Tokenize *t) {
|
|||||||
t->cur_tok->id = TokenIdKeywordAsm;
|
t->cur_tok->id = TokenIdKeywordAsm;
|
||||||
} else if (mem_eql_str(token_mem, token_len, "struct")) {
|
} else if (mem_eql_str(token_mem, token_len, "struct")) {
|
||||||
t->cur_tok->id = TokenIdKeywordStruct;
|
t->cur_tok->id = TokenIdKeywordStruct;
|
||||||
|
} else if (mem_eql_str(token_mem, token_len, "while")) {
|
||||||
|
t->cur_tok->id = TokenIdKeywordWhile;
|
||||||
|
} else if (mem_eql_str(token_mem, token_len, "continue")) {
|
||||||
|
t->cur_tok->id = TokenIdKeywordContinue;
|
||||||
|
} else if (mem_eql_str(token_mem, token_len, "break")) {
|
||||||
|
t->cur_tok->id = TokenIdKeywordBreak;
|
||||||
}
|
}
|
||||||
|
|
||||||
t->cur_tok = nullptr;
|
t->cur_tok = nullptr;
|
||||||
@ -955,6 +961,9 @@ static const char * token_name(Token *token) {
|
|||||||
case TokenIdKeywordVolatile: return "Volatile";
|
case TokenIdKeywordVolatile: return "Volatile";
|
||||||
case TokenIdKeywordAsm: return "Asm";
|
case TokenIdKeywordAsm: return "Asm";
|
||||||
case TokenIdKeywordStruct: return "Struct";
|
case TokenIdKeywordStruct: return "Struct";
|
||||||
|
case TokenIdKeywordWhile: return "While";
|
||||||
|
case TokenIdKeywordContinue: return "Continue";
|
||||||
|
case TokenIdKeywordBreak: return "Break";
|
||||||
case TokenIdLParen: return "LParen";
|
case TokenIdLParen: return "LParen";
|
||||||
case TokenIdRParen: return "RParen";
|
case TokenIdRParen: return "RParen";
|
||||||
case TokenIdComma: return "Comma";
|
case TokenIdComma: return "Comma";
|
||||||
|
@ -32,6 +32,9 @@ enum TokenId {
|
|||||||
TokenIdKeywordAsm,
|
TokenIdKeywordAsm,
|
||||||
TokenIdKeywordVolatile,
|
TokenIdKeywordVolatile,
|
||||||
TokenIdKeywordStruct,
|
TokenIdKeywordStruct,
|
||||||
|
TokenIdKeywordWhile,
|
||||||
|
TokenIdKeywordContinue,
|
||||||
|
TokenIdKeywordBreak,
|
||||||
TokenIdLParen,
|
TokenIdLParen,
|
||||||
TokenIdRParen,
|
TokenIdRParen,
|
||||||
TokenIdComma,
|
TokenIdComma,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user