For loop iterate through arrays and slices

This commit is contained in:
Krzosa Karol
2022-06-19 22:31:59 +02:00
parent 367562f0a8
commit aa5741203f
6 changed files with 67 additions and 14 deletions

View File

@@ -163,6 +163,10 @@ struct Ast_For: Ast{
Ast_Expr *cond; Ast_Expr *cond;
Ast_Expr *iter; Ast_Expr *iter;
Ast_Scope *scope; Ast_Scope *scope;
Ast_Decl *array_traversal_var;
bool is_array_traversal;
bool is_also_slice_traversal;
}; };
struct Ast_Lambda : Ast_Expr { struct Ast_Lambda : Ast_Expr {
@@ -266,9 +270,9 @@ struct Ast_Decl: Ast{
result->pos = ipos; \ result->pos = ipos; \
result->di = ++pctx->unique_ids result->di = ++pctx->unique_ids
#define MAKE_AST(T,kind,pos,flags) (T *)ast_new(sizeof(T), kind, pos, flags) #define new_ast(T,kind,pos,flags) (T *)_new_ast(sizeof(T), kind, pos, flags)
function Ast * function Ast *
ast_new(SizeU size, Ast_Kind kind, Token *pos, Ast_Flag flags = 0){ _new_ast(SizeU size, Ast_Kind kind, Token *pos, Ast_Flag flags = 0){
Ast *result = (Ast *)exp_alloc(pctx->perm, size, AF_ZeroMemory); Ast *result = (Ast *)exp_alloc(pctx->perm, size, AF_ZeroMemory);
result->flags = flags; result->flags = flags;
result->kind = kind; result->kind = kind;

View File

@@ -500,14 +500,41 @@ gen_ast(Ast *ast){
} }
CASE(FOR, For){ CASE(FOR, For){
gen("for(");
if(node->init) gen_expr(node->init); // Array iter
gen(";"); if(node->is_array_traversal){
if(node->cond) gen_expr(node->cond); gen("for(S64 _i%d = 0; _i%d < ", node->pos->line, node->pos->line);
gen(";"); gen_expr(node->cond);
if(node->iter) gen_expr(node->iter); gen(".len; _i%d+=1)", node->pos->line);
gen(")"); gen("{");
gen_stmt_scope(node->scope); global_indent++;
genln("");
gen_simple_decl(node->array_traversal_var->type, node->array_traversal_var->name);
gen(" = ");
gen_expr(node->cond);
if(node->is_also_slice_traversal) gen(".data");
gen(" + _i%d;", node->pos->line);
For(node->scope->stmts) {
gen_line(it);
genln("");
gen_ast(it);
}
global_indent--;
genln("}");
}
// Normal for loop
else{
gen("for(");
if(node->init) gen_expr(node->init);
gen(";");
if(node->cond) gen_expr(node->cond);
gen(";");
if(node->iter) gen_expr(node->iter);
gen(")");
gen_stmt_scope(node->scope);
}
BREAK(); BREAK();
} }

View File

@@ -175,6 +175,7 @@ Intern_String keyword_enum;
Intern_String intern_void; Intern_String intern_void;
Intern_String intern_foreign; Intern_String intern_foreign;
Intern_String intern_it;
Intern_String intern_strict; Intern_String intern_strict;
Intern_String intern_flag; Intern_String intern_flag;
@@ -240,6 +241,7 @@ lex_init(Allocator *token_string_arena, Allocator *map_allocator, Lexer *l){
intern_strict = intern_string(&l->interns, "strict"_s); intern_strict = intern_string(&l->interns, "strict"_s);
intern_void = intern_string(&l->interns, "void"_s); intern_void = intern_string(&l->interns, "void"_s);
intern_flag = intern_string(&l->interns, "flag"_s); intern_flag = intern_string(&l->interns, "flag"_s);
intern_it = intern_string(&l->interns, "it"_s);
} }
function void function void

View File

@@ -234,7 +234,7 @@ parse_stmt_scope(Ast_Scope *scope_defined_outside = 0){
} }
else if(token_match_keyword(keyword_switch)){ else if(token_match_keyword(keyword_switch)){
Ast_Switch *result = MAKE_AST(Ast_Switch, AST_SWITCH, token, AST_STMT); Ast_Switch *result = new_ast(Ast_Switch, AST_SWITCH, token, AST_STMT);
result->value = parse_expr(); result->value = parse_expr();
result->cases = {scratch}; result->cases = {scratch};
@@ -245,7 +245,7 @@ parse_stmt_scope(Ast_Scope *scope_defined_outside = 0){
continue; continue;
} }
Ast_Switch_Case *switch_case = MAKE_AST(Ast_Switch_Case, AST_SWITCH_CASE, token_get(), AST_STMT); Ast_Switch_Case *switch_case = new_ast(Ast_Switch_Case, AST_SWITCH_CASE, token_get(), AST_STMT);
if(token_match_pound(pctx->intern("fallthrough"_s))) if(token_match_pound(pctx->intern("fallthrough"_s)))
switch_case->fallthrough = true; switch_case->fallthrough = true;

View File

@@ -1,5 +1,4 @@
main :: (argc: int, argv: **char): int main :: (argc: int, argv: **char): int
test_arrays() test_arrays()
test_any() test_any()
@@ -14,6 +13,11 @@ test_arrays :: ()
assert(i+1 == array1[i]) assert(i+1 == array1[i])
array6: []*S64 = {&array1[0]} array6: []*S64 = {&array1[0]}
for array1
*it = 0
for i := 0, i < length_of(array1), i+=1
assert(0 == array1[i])
test_any :: () test_any :: ()
some_int_value := 10 some_int_value := 10
thing: Any = some_int_value thing: Any = some_int_value

View File

@@ -566,7 +566,23 @@ resolve_stmt(Ast *ast, Ast_Type *ret){
} }
resolve_expr(node->init, AST_CAN_BE_NULL); resolve_expr(node->init, AST_CAN_BE_NULL);
resolve_and_require_bool("Conditional in a for loop condition", node->cond, AST_CAN_BE_NULL); Operand op = resolve_expr(node->cond, AST_CAN_BE_NULL);
if(node->cond){
if((!node->init && !node->iter) && (is_array(op.type) || is_slice(op.type))){
node->is_array_traversal = true;
if(is_slice(op.type)) node->is_also_slice_traversal = true;
Ast_Decl *var = new_ast(Ast_Decl, AST_VAR, node->cond->pos, AST_DECL);
var->state = DECL_RESOLVED;
var->type = type_pointer(op.type->base);
var->name = intern_it;
insert_into_scope(node->parent_scope, var);
node->array_traversal_var = var;
}
else if(!is_bool(op.type)){
compiler_error(node->pos, "Invalid type of for loop condition %Q, required [Bool]", typestring(op.type));
}
}
resolve_expr(node->iter, AST_CAN_BE_NULL); resolve_expr(node->iter, AST_CAN_BE_NULL);
For(node->scope->stmts) resolve_stmt(it, ret); For(node->scope->stmts) resolve_stmt(it, ret);
BREAK(); BREAK();