Added basic for i loops. Missing some breaking tests and more tests. Also want to add for each at some point and it_index.

This commit is contained in:
2025-08-30 22:58:51 +02:00
parent 14f8b20d5f
commit 94fc3a4dad
7 changed files with 116 additions and 2 deletions

24
AST.jai
View File

@@ -21,6 +21,7 @@ AST_Kind :: enum {
Call; Call;
Struct; Struct;
If; If;
For;
CBuffer; CBuffer;
FieldList; FieldList;
ArgList; ArgList;
@@ -309,6 +310,26 @@ pretty_print_if :: (node : *AST_Node, indentation : int, builder : *String_Build
append(builder, ")"); append(builder, ")");
} }
pretty_print_for :: (node : *AST_Node, indentation : int, builder : *String_Builder, skip_indent := false) {
if !skip_indent {
indent(builder, indentation);
}
append(builder, "(for ");
loop_iterator := node.token;
print_to_builder(builder, "% : ", loop_iterator.ident_value);
pretty_print_node(node.children[0], 0, builder);
append(builder, "..");
pretty_print_node(node.children[1], 0, builder);
append(builder, "\n");
pretty_print_node(node.children[2], indentation + 4, builder);
append(builder, ")");
}
print_expression_statement :: (node : *AST_Node, indentation : int, builder : *String_Builder, skip_indent := false) { print_expression_statement :: (node : *AST_Node, indentation : int, builder : *String_Builder, skip_indent := false) {
if !skip_indent { if !skip_indent {
indent(builder, indentation); indent(builder, indentation);
@@ -327,6 +348,9 @@ pretty_print_node :: (node : *AST_Node, indentation : int, builder : *String_Bui
case .If; { case .If; {
pretty_print_if(node, indentation, builder, skip_indent); pretty_print_if(node, indentation, builder, skip_indent);
} }
case .For; {
pretty_print_for(node, indentation, builder, skip_indent);
}
case .Struct; case .Struct;
case .ArgList; { case .ArgList; {
pretty_print_arglist(node, indentation + 2, builder, skip_indent); pretty_print_arglist(node, indentation + 2, builder, skip_indent);

View File

@@ -494,6 +494,26 @@ emit_node :: (state : *Codegen_State, node : *AST_Node, indentation : int) {
emit_node(state, node.children[0], 0); emit_node(state, node.children[0], 0);
append(*state.builder, ";"); append(*state.builder, ";");
} }
case .For; {
if node.parent.kind != .For {
indent(*state.builder, indentation);
}
append(*state.builder, "for ");
loop_ident := node.token.ident_value;
begin_val := node.children[0].integer_value;
end_val := node.children[1].integer_value;
print_to_builder(*state.builder, "(int % = %; % < %; %++)\n", loop_ident, begin_val, loop_ident, end_val, loop_ident);
indent(*state.builder, indentation);
append(*state.builder, "{\n");
emit_block(state, node.children[2], indentation + 1);
indent(*state.builder, indentation);
append(*state.builder, "}\n");
}
case .If; { case .If; {
if node.parent.kind != .If { if node.parent.kind != .If {
indent(*state.builder, indentation); indent(*state.builder, indentation);

View File

@@ -54,6 +54,7 @@ Token_Kind :: enum {
TOKEN_SEMICOLON; TOKEN_SEMICOLON;
TOKEN_COMMA; TOKEN_COMMA;
TOKEN_DOT; TOKEN_DOT;
TOKEN_DOTDOT;
TOKEN_IDENTIFIER; TOKEN_IDENTIFIER;
@@ -491,7 +492,10 @@ scan_next_token :: (lexer : *Lexer) -> *Token {
} }
case #char ";"; return make_token(lexer, .TOKEN_SEMICOLON); case #char ";"; return make_token(lexer, .TOKEN_SEMICOLON);
case #char ","; return make_token(lexer, .TOKEN_COMMA); case #char ","; return make_token(lexer, .TOKEN_COMMA);
case #char "."; return make_token(lexer, .TOKEN_DOT); case #char "."; {
if match_character(lexer, #char ".") return make_token(lexer, .TOKEN_DOTDOT);
return make_token(lexer, .TOKEN_DOT);
}
} }
s : string = .{ count = 1, data = *c }; s : string = .{ count = 1, data = *c };

View File

@@ -888,6 +888,35 @@ statement :: (parse_state : *Parse_State) -> *AST_Node {
return error_node(parse_state, "'else' without 'if'."); return error_node(parse_state, "'else' without 'if'.");
} }
} else if match(parse_state, .TOKEN_FOR) {
if check(parse_state, .TOKEN_IDENTIFIER) {
node := make_node(parse_state, .For);
source_location : Source_Range;
source_location.begin = parse_state.previous;
loop_iterator := parse_state.current;
node.token = loop_iterator;
advance(parse_state);
consume(parse_state, .TOKEN_COLON, "Expect ':' after for loop iterator.");
begin_iter := expression(parse_state);
add_child(node, begin_iter);
consume(parse_state, .TOKEN_DOTDOT, "Expect '..' after for loop iter left hand side.");
end_iter := expression(parse_state);
add_child(node, end_iter);
for_body := block(parse_state);
add_child(node, for_body);
// consume(parse_state, .TOKEN_RIGHTBRACE, "Expect '}' after for body.");
node.source_location = source_location;
return node;
}
} else { } else {
return expression_statement(parse_state); return expression_statement(parse_state);
} }

View File

@@ -1485,6 +1485,33 @@ check_node :: (checker : *Semantic_Checker, node : *AST_Node) -> Type_Variable_H
case .Return; { case .Return; {
return check_node(checker, node.children[0]); return check_node(checker, node.children[0]);
} }
case .For; {
loop_iterator := node.token;
symbol : Defined_Symbol;
symbol.name = loop_iterator.ident_value;
symbol.source_node = node;
variable, handle := new_type_variable(checker);
variable.name = symbol.name;
typename : string;
variable.type = .Int;
symbol.type_variable = handle;
add_symbol_to_scope(checker.state, *checker.result.scope_stack, checker.current_scope, symbol.name, symbol);
begin_iter := check_node(checker, node.children[0]);
begin_var := from_handle(checker, begin_iter);
if begin_var.type != .Int {
}
end_iter := check_node(checker, node.children[1]);
end_var := from_handle(checker, end_iter);
if end_var.type != .Int {
}
check_block(checker, node.children[2]);
}
case .If; { case .If; {
cond_var := check_node(checker, node.children[0]); cond_var := check_node(checker, node.children[0]);

6
test/for_i_loop.ink Normal file
View File

@@ -0,0 +1,6 @@
vertex main :: () {
x := 0;
for i : 0..10 {
x += 1.0;
}
}

4
test/for_i_one_liner.ink Normal file
View File

@@ -0,0 +1,4 @@
vertex main :: () {
x := 0.0;
for i : 0..10 x += 2.0;
}