about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorBaitinq <[email protected]>2025-07-09 23:05:40 +0200
committerBaitinq <[email protected]>2025-07-09 23:05:40 +0200
commit94ffd157cf364529eb0415ee8054f6e8644f784f (patch)
treed5cddc390223cb34ade7ff3e6b2f7e218ffdf0cf /src
parentBootstrap: Support unary expressions (diff)
downloadpry-lang-94ffd157cf364529eb0415ee8054f6e8644f784f.tar.gz
pry-lang-94ffd157cf364529eb0415ee8054f6e8644f784f.tar.bz2
pry-lang-94ffd157cf364529eb0415ee8054f6e8644f784f.zip
Bootstrap: Support while loops
Diffstat (limited to 'src')
-rw-r--r--src/bootstrap/codegen.pry40
-rw-r--r--src/bootstrap/parser.pry54
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");