diff options
| author | Baitinq <[email protected]> | 2025-07-09 23:05:40 +0200 |
|---|---|---|
| committer | Baitinq <[email protected]> | 2025-07-09 23:05:40 +0200 |
| commit | 94ffd157cf364529eb0415ee8054f6e8644f784f (patch) | |
| tree | d5cddc390223cb34ade7ff3e6b2f7e218ffdf0cf | |
| parent | Bootstrap: Support unary expressions (diff) | |
| download | pry-lang-94ffd157cf364529eb0415ee8054f6e8644f784f.tar.gz pry-lang-94ffd157cf364529eb0415ee8054f6e8644f784f.tar.bz2 pry-lang-94ffd157cf364529eb0415ee8054f6e8644f784f.zip | |
Bootstrap: Support while loops
| -rw-r--r-- | src/bootstrap/codegen.pry | 40 | ||||
| -rw-r--r-- | src/bootstrap/parser.pry | 54 |
2 files changed, 92 insertions, 2 deletions
diff --git a/src/bootstrap/codegen.pry b/src/bootstrap/codegen.pry index 9062ba1..dd3e597 100644 --- a/src/bootstrap/codegen.pry +++ b/src/bootstrap/codegen.pry @@ -88,6 +88,8 @@ let codegen = struct { arena: *arena, environment: *Environment, + whil_loop_exit: LLVMBasicBlockRef, + whil_block: LLVMBasicBlockRef, current_function: LLVMValueRef, current_function_retur_type: *Node, }; @@ -765,6 +767,39 @@ let codegen_generate_if_statement = (c: *codegen, statement: *NODE_IF_STATEMENT_ return null; }; +let codegen_generate_while_statement = (c: *codegen, statement: *NODE_WHILE_STATEMENT_DATA) => *void { + let whil_block = LLVMAppendBasicBlock((*c).current_function, "while_block"); + LLVMBuildBr((*c).builder, whil_block); + LLVMPositionBuilderAtEnd((*c).builder, whil_block); + + let condition_value = codegen_generate_expression_value(c, (*statement).condition, cast(*i8, null)); + assert(condition_value != cast(*Variable, null)); + + let inner_block = LLVMAppendBasicBlock((*c).current_function, "inner_block"); + let outer_block = LLVMAppendBasicBlock((*c).current_function, "outer_block"); + LLVMBuildCondBr((*c).builder, (*condition_value).value, inner_block, outer_block); + + (*c).whil_loop_exit = outer_block; + (*c).whil_block = whil_block; + + LLVMPositionBuilderAtEnd((*c).builder, inner_block); + let i = 0; + while i < (*statement).statements_len { + let stmt = (*((*statement).statements + cast(**Node, i))); + let res = codegen_generate_statement(c, stmt); + assert(res == 0); + i = i + 1; + }; + + LLVMBuildBr((*c).builder, whil_block); + LLVMPositionBuilderAtEnd((*c).builder, outer_block); + + (*c).whil_loop_exit = cast(LLVMBasicBlockRef, null); + (*c).whil_block = cast(LLVMBasicBlockRef, null); + + return null; +}; + let codegen_generate_statement = (c: *codegen, statement: *Node) => i64 { let stmt = *statement; @@ -785,6 +820,11 @@ let codegen_generate_statement = (c: *codegen, statement: *Node) => i64 { codegen_generate_if_statement(c, cast(*NODE_IF_STATEMENT_DATA, stmt.data)); return 0; }; + + if stmt.type == NODE_WHILE_STATEMENT { + codegen_generate_while_statement(c, cast(*NODE_WHILE_STATEMENT_DATA, stmt.data)); + return 0; + }; printf("ASSERT 3 %d\n", stmt.type); assert(false); diff --git a/src/bootstrap/parser.pry b/src/bootstrap/parser.pry index cb8c269..95e654e 100644 --- a/src/bootstrap/parser.pry +++ b/src/bootstrap/parser.pry @@ -403,6 +403,48 @@ let parser_parse_if_statement = (p: *parser) => *Node { return create_node(p, r); }; +/* WhileStatement ::= "while" Expression LBRACE Statement* RBRACE */ +let parser_parse_while_statement = (p: *parser) => *Node { + if parser_accept_token(p, TOKEN_WHILE) == cast(*token, null) { + return cast(*Node, null); + }; + + let expression = parser_parse_expression(p); + if expression == cast(*Node, null) { + return cast(*Node, null); + }; + + if parser_accept_token(p, TOKEN_LBRACE) == cast(*token, null) { + return cast(*Node, null); + }; + + let statements = cast(**Node, arena_alloc((*p).arena, sizeof(*Node) * 100)); + let i = 0; + while true { + let n = parser_accept_parse(p, parser_parse_statement); + if n == cast(*Node, null) { + break; + }; + (*(statements + cast(**Node, i))) = n; + i = i + 1; + }; + + if parser_accept_token(p, TOKEN_RBRACE) == cast(*token, null) { + return cast(*Node, null); + }; + + let dd = cast(*NODE_WHILE_STATEMENT_DATA, arena_alloc((*p).arena, sizeof(NODE_WHILE_STATEMENT_DATA))); + (*dd).condition = expression; + (*dd).statements = statements; + (*dd).statements_len = i; + + let r = Node{}; + r.type = NODE_WHILE_STATEMENT; + r.data = cast(*void, dd); + + return create_node(p, r); +}; + /* ExternDeclaration ::= "extern" IDENTIFIER EQUALS Type */ let parser_parse_extern_declaration = (p: *parser) => *Node { if parser_accept_token(p, TOKEN_EXTERN) == cast(*token, null) { @@ -607,10 +649,10 @@ let parser_parse_equality_expression = (p: *parser) => *Node { let typ = -1; let ex = parser_accept_parse(p, (ip: *parser) => *Node { - if parser_accept_token(ip, TOKEN_BANG) == cast(*token, null) { + if parser_accept_token(ip, TOKEN_EQUALS) == cast(*token, null) { return cast(*Node, null); }; - if parser_accept_token(ip, TOKEN_BANG) == cast(*token, null) { + if parser_accept_token(ip, TOKEN_EQUALS) == cast(*token, null) { return cast(*Node, null); }; let n = Node{}; @@ -959,6 +1001,14 @@ let parser_parse_statement = (p: *parser) => *Node { }; return retu; }; + + let retu = parser_accept_parse(p, parser_parse_while_statement); + if retu != cast(*Node, null) { + if parser_accept_token(p, TOKEN_SEMICOLON) == cast(*token, null) { + return cast(*Node, null); + }; + return retu; + }; printf("None\n"); |