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:
24
AST.jai
24
AST.jai
@@ -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);
|
||||||
|
|||||||
20
Codegen.jai
20
Codegen.jai
@@ -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);
|
||||||
|
|||||||
@@ -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 };
|
||||||
|
|||||||
29
Parsing.jai
29
Parsing.jai
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
6
test/for_i_loop.ink
Normal 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
4
test/for_i_one_liner.ink
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
vertex main :: () {
|
||||||
|
x := 0.0;
|
||||||
|
for i : 0..10 x += 2.0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user