diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/bootstrap/codegen.pry | 40 | ||||
| -rw-r--r-- | src/bootstrap/llvm.pry | 5 | ||||
| -rw-r--r-- | src/bootstrap/parser.pry | 50 |
3 files changed, 94 insertions, 1 deletions
diff --git a/src/bootstrap/codegen.pry b/src/bootstrap/codegen.pry index 55be4fa..8b95451 100644 --- a/src/bootstrap/codegen.pry +++ b/src/bootstrap/codegen.pry @@ -470,7 +470,6 @@ let codegen_generate_expression_value = (c: *codegen, expression: *Node, name: * /* TODO: Move to defer */ (*c).current_function = last_function; environment_drop_scope((*c).environment); - return codegen_create_variable(c, v); }; @@ -634,6 +633,40 @@ let codegen_generate_function_call_statement = (c: *codegen, statement: *Node) = return codegen_create_variable(c, v); }; +let codegen_generate_if_statement = (c: *codegen, statement: *NODE_IF_STATEMENT_DATA) => *void { + let condition_value = codegen_generate_expression_value(c, (*statement).condition, cast(*i8, null)); + assert(condition_value != cast(*Variable, null)); + + let current_block = LLVMGetInsertBlock((*c).builder); + + let then_block = LLVMAppendBasicBlock((*c).current_function, "then_block"); + LLVMPositionBuilderAtEnd((*c).builder, then_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; + }; + + let merge_block = LLVMAppendBasicBlock((*c).current_function, "merge_block"); + let last_instr = LLVMGetLastInstruction(LLVMGetInsertBlock((*c).builder)); + if last_instr == cast(LLVMValueRef, null) { + LLVMBuildBr((*c).builder, merge_block); + }; + if last_instr != cast(LLVMValueRef, null) { + if LLVMIsATerminatorInst(last_instr) == cast(LLVMValueRef, null) { + LLVMBuildBr((*c).builder, merge_block); + }; + }; + LLVMPositionBuilderAtEnd((*c).builder, current_block); + LLVMBuildCondBr((*c).builder, (*condition_value).value, then_block, merge_block); + LLVMPositionBuilderAtEnd((*c).builder, merge_block); + + return null; +}; + let codegen_generate_statement = (c: *codegen, statement: *Node) => i64 { let stmt = *statement; @@ -649,6 +682,11 @@ let codegen_generate_statement = (c: *codegen, statement: *Node) => i64 { codegen_generate_function_call_statement(c, statement); return 0; }; + + if stmt.type == NODE_IF_STATEMENT { + codegen_generate_if_statement(c, cast(*NODE_IF_STATEMENT_DATA, stmt.data)); + return 0; + }; printf("ASSERT 3 %d\n", stmt.type); assert(false); diff --git a/src/bootstrap/llvm.pry b/src/bootstrap/llvm.pry index 4183b99..51ab978 100644 --- a/src/bootstrap/llvm.pry +++ b/src/bootstrap/llvm.pry @@ -310,3 +310,8 @@ extern LLVMBuildGlobalStringPtr = (LLVMBuilderRef, *i8, *i8) => LLVMValueRef; extern LLVMBuildAlloca = (LLVMBuilderRef, LLVMTypeRef, *i8) => LLVMValueRef; extern LLVMBuildStore = (LLVMBuilderRef, LLVMValueRef, LLVMValueRef) => LLVMValueRef; extern LLVMBuildLoad2 = (LLVMBuilderRef, LLVMTypeRef, LLVMValueRef, *i8) => LLVMValueRef; +extern LLVMGetLastInstruction = (LLVMBasicBlockRef) => LLVMValueRef; + +extern LLVMBuildBr = (LLVMBuilderRef, LLVMBasicBlockRef) => LLVMValueRef; +extern LLVMIsATerminatorInst = (LLVMValueRef) => LLVMValueRef; +extern LLVMBuildCondBr = (LLVMBuilderRef, LLVMValueRef, LLVMBasicBlockRef, LLVMBasicBlockRef) => LLVMValueRef; diff --git a/src/bootstrap/parser.pry b/src/bootstrap/parser.pry index be1ffb7..95f847b 100644 --- a/src/bootstrap/parser.pry +++ b/src/bootstrap/parser.pry @@ -360,6 +360,48 @@ let parser_parse_type = (p: *parser) => *Node { return cast(*Node, null); }; +/* IfStatement ::= "if" Expression LBRACE Statement* RBRACE */ +let parser_parse_if_statement = (p: *parser) => *Node { + if parser_accept_token(p, TOKEN_IF) == 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_IF_STATEMENT_DATA, arena_alloc((*p).arena, sizeof(NODE_IF_STATEMENT_DATA))); + (*dd).condition = expression; + (*dd).statements = statements; + (*dd).statements_len = i; + + let r = Node{}; + r.type = NODE_IF_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) { @@ -807,6 +849,14 @@ let parser_parse_statement = (p: *parser) => *Node { }; return retu; }; + + let retu = parser_accept_parse(p, parser_parse_if_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"); |