// #target: macos-x64
module test;
import std::io;
alias IntFn = fn int();

macro IntFn @dofn($m, $n) {
    return fn int () => $m;
}

macro IntFn[*] @doallfn($n) {
    IntFn[$n] $vec;
    $for var $i = 0; $i < $n; $i++:
        $vec[$i] = @dofn($i, $i);
    $endfor
    return $vec;
}

IntFn[*] lambda_arr = @doallfn(3);

fn void main()
{
	int x;
    $for var $i = 0; $i < 4; $i++:
        x = @dofn($i, 0)();
    $endfor
    $for var $i = 0; $i < 4; $i++:
        x = @dofn($i, 1)();
    $endfor
	foreach (i : lambda_arr)
	{
		x = i();
	}
}

/* #expect: test.ll


define void @test.main() #0 {
entry:
  %x = alloca i32, align 4
  %.anon = alloca i64, align 8
  %i = alloca ptr, align 8
  store i32 0, ptr %x, align 4
  %0 = call i32 @"test.$global$lambda1"()
  store i32 %0, ptr %x, align 4
  %1 = call i32 @"test.@dofn$lambda4"()
  store i32 %1, ptr %x, align 4
  %2 = call i32 @"test.@dofn$lambda5"()
  store i32 %2, ptr %x, align 4
  %3 = call i32 @"test.@dofn$lambda6"()
  store i32 %3, ptr %x, align 4
  %4 = call i32 @"test.@dofn$lambda7"()
  store i32 %4, ptr %x, align 4
  %5 = call i32 @"test.$global$lambda2"()
  store i32 %5, ptr %x, align 4
  %6 = call i32 @"test.@dofn$lambda5"()
  store i32 %6, ptr %x, align 4
  %7 = call i32 @"test.@dofn$lambda6"()
  store i32 %7, ptr %x, align 4
  store i64 0, ptr %.anon, align 8
  br label %loop.cond

loop.cond:                                        ; preds = %loop.body, %entry
  %8 = load i64, ptr %.anon, align 8
  %gt = icmp ugt i64 3, %8
  br i1 %gt, label %loop.body, label %loop.exit

loop.body:                                        ; preds = %loop.cond
  %9 = load i64, ptr %.anon, align 8
  %ptroffset = getelementptr inbounds [8 x i8], ptr @test.lambda_arr, i64 %9
  %10 = load ptr, ptr %ptroffset, align 8
  store ptr %10, ptr %i, align 8
  %11 = load ptr, ptr %i, align 8
  %12 = call i32 %11()
  store i32 %12, ptr %x, align 4
  %13 = load i64, ptr %.anon, align 8
  %addnuw = add nuw i64 %13, 1
  store i64 %addnuw, ptr %.anon, align 8
  br label %loop.cond

loop.exit:                                        ; preds = %loop.cond
  ret void
}

define internal i32 @"test.@dofn$lambda4"() #0 {
entry:
  ret i32 1
}

define internal i32 @"test.@dofn$lambda5"() #0 {
entry:
  ret i32 2
}

define internal i32 @"test.@dofn$lambda6"() #0 {
entry:
  ret i32 3
}

define internal i32 @"test.@dofn$lambda7"() #0 {
entry:
  ret i32 0
}

define i32 @"test.$global$lambda3"() #0 {
entry:
  ret i32 2
}

define i32 @"test.$global$lambda2"() #0 {
entry:
  ret i32 1
}

define i32 @"test.$global$lambda1"() #0 {
entry:
  ret i32 0
}
