Commit 259f3458a1

Andrew Kelley <andrew@ziglang.org>
2021-08-07 20:07:48
Sema: implement alloc_inferred_comptime
1 parent 5789036
Changed files (4)
src/Sema.zig
@@ -139,7 +139,7 @@ pub fn analyzeBody(
             .alloc                        => try sema.zirAlloc(block, inst),
             .alloc_inferred               => try sema.zirAllocInferred(block, inst, Type.initTag(.inferred_alloc_const)),
             .alloc_inferred_mut           => try sema.zirAllocInferred(block, inst, Type.initTag(.inferred_alloc_mut)),
-            .alloc_inferred_comptime      => try sema.zirAllocInferredComptime(block, inst),
+            .alloc_inferred_comptime      => try sema.zirAllocInferredComptime(inst),
             .alloc_mut                    => try sema.zirAllocMut(block, inst),
             .alloc_comptime               => try sema.zirAllocComptime(block, inst),
             .anyframe_type                => try sema.zirAnyframeType(block, inst),
@@ -1384,10 +1384,14 @@ fn zirAllocComptime(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Comp
     return sema.analyzeComptimeAlloc(block, var_type);
 }
 
-fn zirAllocInferredComptime(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
+fn zirAllocInferredComptime(sema: *Sema, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
     const src_node = sema.code.instructions.items(.data)[inst].node;
     const src: LazySrcLoc = .{ .node_offset = src_node };
-    return sema.mod.fail(&block.base, src, "TODO implement Sema.zirAllocInferredComptime", .{});
+    sema.src = src;
+    return sema.addConstant(
+        Type.initTag(.inferred_alloc_mut),
+        try Value.Tag.inferred_alloc_comptime.create(sema.arena, undefined),
+    );
 }
 
 fn zirAlloc(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
test/behavior/eval.zig
@@ -63,146 +63,12 @@ fn constExprEvalOnSingleExprBlocksFn(x: i32, b: bool) i32 {
     return result;
 }
 
-test "statically initialized list" {
-    try expect(static_point_list[0].x == 1);
-    try expect(static_point_list[0].y == 2);
-    try expect(static_point_list[1].x == 3);
-    try expect(static_point_list[1].y == 4);
-}
-const Point = struct {
-    x: i32,
-    y: i32,
-};
-const static_point_list = [_]Point{
-    makePoint(1, 2),
-    makePoint(3, 4),
-};
-fn makePoint(x: i32, y: i32) Point {
-    return Point{
-        .x = x,
-        .y = y,
-    };
-}
-
-test "static eval list init" {
-    try expect(static_vec3.data[2] == 1.0);
-    try expect(vec3(0.0, 0.0, 3.0).data[2] == 3.0);
-}
-const static_vec3 = vec3(0.0, 0.0, 1.0);
-pub const Vec3 = struct {
-    data: [3]f32,
-};
-pub fn vec3(x: f32, y: f32, z: f32) Vec3 {
-    return Vec3{
-        .data = [_]f32{
-            x,
-            y,
-            z,
-        },
-    };
-}
-
 test "constant expressions" {
     var array: [array_size]u8 = undefined;
     try expect(@sizeOf(@TypeOf(array)) == 20);
 }
 const array_size: u8 = 20;
 
-test "constant struct with negation" {
-    try expect(vertices[0].x == -0.6);
-}
-const Vertex = struct {
-    x: f32,
-    y: f32,
-    r: f32,
-    g: f32,
-    b: f32,
-};
-const vertices = [_]Vertex{
-    Vertex{
-        .x = -0.6,
-        .y = -0.4,
-        .r = 1.0,
-        .g = 0.0,
-        .b = 0.0,
-    },
-    Vertex{
-        .x = 0.6,
-        .y = -0.4,
-        .r = 0.0,
-        .g = 1.0,
-        .b = 0.0,
-    },
-    Vertex{
-        .x = 0.0,
-        .y = 0.6,
-        .r = 0.0,
-        .g = 0.0,
-        .b = 1.0,
-    },
-};
-
-test "statically initialized struct" {
-    st_init_str_foo.x += 1;
-    try expect(st_init_str_foo.x == 14);
-}
-const StInitStrFoo = struct {
-    x: i32,
-    y: bool,
-};
-var st_init_str_foo = StInitStrFoo{
-    .x = 13,
-    .y = true,
-};
-
-test "statically initalized array literal" {
-    const y: [4]u8 = st_init_arr_lit_x;
-    try expect(y[3] == 4);
-}
-const st_init_arr_lit_x = [_]u8{
-    1,
-    2,
-    3,
-    4,
-};
-
-test "const slice" {
-    comptime {
-        const a = "1234567890";
-        try expect(a.len == 10);
-        const b = a[1..2];
-        try expect(b.len == 1);
-        try expect(b[0] == '2');
-    }
-}
-
-test "try to trick eval with runtime if" {
-    try expect(testTryToTrickEvalWithRuntimeIf(true) == 10);
-}
-
-fn testTryToTrickEvalWithRuntimeIf(b: bool) usize {
-    comptime var i: usize = 0;
-    inline while (i < 10) : (i += 1) {
-        const result = if (b) false else true;
-        _ = result;
-    }
-    comptime {
-        return i;
-    }
-}
-
-test "inlined loop has array literal with elided runtime scope on first iteration but not second iteration" {
-    var runtime = [1]i32{3};
-    comptime var i: usize = 0;
-    inline while (i < 2) : (i += 1) {
-        const result = if (i == 0) [1]i32{2} else runtime;
-        _ = result;
-    }
-    comptime {
-        try expect(i == 2);
-    }
-}
-
 fn max(comptime T: type, a: T, b: T) T {
     if (T == bool) {
         return a or b;
@@ -229,52 +95,6 @@ test "inlined block and runtime block phi" {
     }
 }
 
-const CmdFn = struct {
-    name: []const u8,
-    func: fn (i32) i32,
-};
-
-const cmd_fns = [_]CmdFn{
-    CmdFn{
-        .name = "one",
-        .func = one,
-    },
-    CmdFn{
-        .name = "two",
-        .func = two,
-    },
-    CmdFn{
-        .name = "three",
-        .func = three,
-    },
-};
-fn one(value: i32) i32 {
-    return value + 1;
-}
-fn two(value: i32) i32 {
-    return value + 2;
-}
-fn three(value: i32) i32 {
-    return value + 3;
-}
-
-fn performFn(comptime prefix_char: u8, start_value: i32) i32 {
-    var result: i32 = start_value;
-    comptime var i = 0;
-    inline while (i < cmd_fns.len) : (i += 1) {
-        if (cmd_fns[i].name[0] == prefix_char) {
-            result = cmd_fns[i].func(result);
-        }
-    }
-    return result;
-}
-
-test "comptime iterate over fn ptr list" {
-    try expect(performFn('t', 1) == 6);
-    try expect(performFn('o', 0) == 1);
-    try expect(performFn('w', 99) == 99);
-}
-
 test "eval @setRuntimeSafety at compile-time" {
     const result = comptime fnWithSetRuntimeSafety();
     try expect(result == 1234);
@@ -285,90 +105,6 @@ fn fnWithSetRuntimeSafety() i32 {
     return 1234;
 }
 
-test "eval @setFloatMode at compile-time" {
-    const result = comptime fnWithFloatMode();
-    try expect(result == 1234.0);
-}
-
-fn fnWithFloatMode() f32 {
-    @setFloatMode(std.builtin.FloatMode.Strict);
-    return 1234.0;
-}
-
-const SimpleStruct = struct {
-    field: i32,
-
-    fn method(self: *const SimpleStruct) i32 {
-        return self.field + 3;
-    }
-};
-
-var simple_struct = SimpleStruct{ .field = 1234 };
-
-const bound_fn = simple_struct.method;
-
-test "call method on bound fn referring to var instance" {
-    try expect(bound_fn() == 1237);
-}
-
-test "ptr to local array argument at comptime" {
-    comptime {
-        var bytes: [10]u8 = undefined;
-        modifySomeBytes(bytes[0..]);
-        try expect(bytes[0] == 'a');
-        try expect(bytes[9] == 'b');
-    }
-}
-
-fn modifySomeBytes(bytes: []u8) void {
-    bytes[0] = 'a';
-    bytes[9] = 'b';
-}
-
-test "comparisons 0 <= uint and 0 > uint should be comptime" {
-    testCompTimeUIntComparisons(1234);
-}
-fn testCompTimeUIntComparisons(x: u32) void {
-    if (!(0 <= x)) {
-        @compileError("this condition should be comptime known");
-    }
-    if (0 > x) {
-        @compileError("this condition should be comptime known");
-    }
-    if (!(x >= 0)) {
-        @compileError("this condition should be comptime known");
-    }
-    if (x < 0) {
-        @compileError("this condition should be comptime known");
-    }
-}
-
-test "const ptr to variable data changes at runtime" {
-    try expect(foo_ref.name[0] == 'a');
-    foo_ref.name = "b";
-    try expect(foo_ref.name[0] == 'b');
-}
-
-const Foo = struct {
-    name: []const u8,
-};
-
-var foo_contents = Foo{ .name = "a" };
-const foo_ref = &foo_contents;
-
-test "create global array with for loop" {
-    try expect(global_array[5] == 5 * 5);
-    try expect(global_array[9] == 9 * 9);
-}
-
-const global_array = x: {
-    var result: [10]usize = undefined;
-    for (result) |*item, index| {
-        item.* = index * index;
-    }
-    break :x result;
-};
-
 test "compile-time downcast when the bits fit" {
     comptime {
         const spartan_count: u16 = 255;
@@ -377,231 +113,6 @@ test "compile-time downcast when the bits fit" {
     }
 }
 
-const hi1 = "hi";
-const hi2 = hi1;
-test "const global shares pointer with other same one" {
-    try assertEqualPtrs(&hi1[0], &hi2[0]);
-    comptime try expect(&hi1[0] == &hi2[0]);
-}
-fn assertEqualPtrs(ptr1: *const u8, ptr2: *const u8) !void {
-    try expect(ptr1 == ptr2);
-}
-
-test "@setEvalBranchQuota" {
-    comptime {
-        // 1001 for the loop and then 1 more for the expect fn call
-        @setEvalBranchQuota(1002);
-        var i = 0;
-        var sum = 0;
-        while (i < 1001) : (i += 1) {
-            sum += i;
-        }
-        try expect(sum == 500500);
-    }
-}
-
-test "float literal at compile time not lossy" {
-    try expect(16777216.0 + 1.0 == 16777217.0);
-    try expect(9007199254740992.0 + 1.0 == 9007199254740993.0);
-}
-
-test "f32 at compile time is lossy" {
-    try expect(@as(f32, 1 << 24) + 1 == 1 << 24);
-}
-
-test "f64 at compile time is lossy" {
-    try expect(@as(f64, 1 << 53) + 1 == 1 << 53);
-}
-
-test "f128 at compile time is lossy" {
-    try expect(@as(f128, 10384593717069655257060992658440192.0) + 1 == 10384593717069655257060992658440192.0);
-}
-
-test {
-    comptime try expect(@as(f128, 1 << 113) == 10384593717069655257060992658440192);
-}
-
-pub fn TypeWithCompTimeSlice(comptime field_name: []const u8) type {
-    _ = field_name;
-    return struct {
-        pub const Node = struct {};
-    };
-}
-
-test "string literal used as comptime slice is memoized" {
-    const a = "link";
-    const b = "link";
-    comptime try expect(TypeWithCompTimeSlice(a).Node == TypeWithCompTimeSlice(b).Node);
-    comptime try expect(TypeWithCompTimeSlice("link").Node == TypeWithCompTimeSlice("link").Node);
-}
-
-test "comptime slice of undefined pointer of length 0" {
-    const slice1 = @as([*]i32, undefined)[0..0];
-    try expect(slice1.len == 0);
-    const slice2 = @as([*]i32, undefined)[100..100];
-    try expect(slice2.len == 0);
-}
-
-fn copyWithPartialInline(s: []u32, b: []u8) void {
-    comptime var i: usize = 0;
-    inline while (i < 4) : (i += 1) {
-        s[i] = 0;
-        s[i] |= @as(u32, b[i * 4 + 0]) << 24;
-        s[i] |= @as(u32, b[i * 4 + 1]) << 16;
-        s[i] |= @as(u32, b[i * 4 + 2]) << 8;
-        s[i] |= @as(u32, b[i * 4 + 3]) << 0;
-    }
-}
-
-test "binary math operator in partially inlined function" {
-    var s: [4]u32 = undefined;
-    var b: [16]u8 = undefined;
-
-    for (b) |*r, i|
-        r.* = @intCast(u8, i + 1);
-
-    copyWithPartialInline(s[0..], b[0..]);
-    try expect(s[0] == 0x1020304);
-    try expect(s[1] == 0x5060708);
-    try expect(s[2] == 0x90a0b0c);
-    try expect(s[3] == 0xd0e0f10);
-}
-
-test "comptime function with the same args is memoized" {
-    comptime {
-        try expect(MakeType(i32) == MakeType(i32));
-        try expect(MakeType(i32) != MakeType(f64));
-    }
-}
-
-fn MakeType(comptime T: type) type {
-    return struct {
-        field: T,
-    };
-}
-
-test "comptime function with mutable pointer is not memoized" {
-    comptime {
-        var x: i32 = 1;
-        const ptr = &x;
-        increment(ptr);
-        increment(ptr);
-        try expect(x == 3);
-    }
-}
-
-fn increment(value: *i32) void {
-    value.* += 1;
-}
-
-fn generateTable(comptime T: type) [1010]T {
-    var res: [1010]T = undefined;
-    var i: usize = 0;
-    while (i < 1010) : (i += 1) {
-        res[i] = @intCast(T, i);
-    }
-    return res;
-}
-
-fn doesAlotT(comptime T: type, value: usize) T {
-    @setEvalBranchQuota(5000);
-    const table = comptime blk: {
-        break :blk generateTable(T);
-    };
-    return table[value];
-}
-
-test "@setEvalBranchQuota at same scope as generic function call" {
-    try expect(doesAlotT(u32, 2) == 2);
-}
-
-test "comptime slice of slice preserves comptime var" {
-    comptime {
-        var buff: [10]u8 = undefined;
-        buff[0..][0..][0] = 1;
-        try expect(buff[0..][0..][0] == 1);
-    }
-}
-
-test "comptime slice of pointer preserves comptime var" {
-    comptime {
-        var buff: [10]u8 = undefined;
-        var a = @ptrCast([*]u8, &buff);
-        a[0..1][0] = 1;
-        try expect(buff[0..][0..][0] == 1);
-    }
-}
-
-const SingleFieldStruct = struct {
-    x: i32,
-
-    fn read_x(self: *const SingleFieldStruct) i32 {
-        return self.x;
-    }
-};
-test "const ptr to comptime mutable data is not memoized" {
-    comptime {
-        var foo = SingleFieldStruct{ .x = 1 };
-        try expect(foo.read_x() == 1);
-        foo.x = 2;
-        try expect(foo.read_x() == 2);
-    }
-}
-
-test "array concat of slices gives slice" {
-    comptime {
-        var a: []const u8 = "aoeu";
-        var b: []const u8 = "asdf";
-        const c = a ++ b;
-        try expect(std.mem.eql(u8, c, "aoeuasdf"));
-    }
-}
-
-test "comptime shlWithOverflow" {
-    const ct_shifted: u64 = comptime amt: {
-        var amt = @as(u64, 0);
-        _ = @shlWithOverflow(u64, ~@as(u64, 0), 16, &amt);
-        break :amt amt;
-    };
-
-    const rt_shifted: u64 = amt: {
-        var amt = @as(u64, 0);
-        _ = @shlWithOverflow(u64, ~@as(u64, 0), 16, &amt);
-        break :amt amt;
-    };
-
-    try expect(ct_shifted == rt_shifted);
-}
-
-test "comptime shl" {
-    var a: u128 = 3;
-    var b: u7 = 63;
-    var c: u128 = 3 << 63;
-    try expectEqual(a << b, c);
-}
-
-test "runtime 128 bit integer division" {
-    var a: u128 = 152313999999999991610955792383;
-    var b: u128 = 10000000000000000000;
-    var c = a / b;
-    try expect(c == 15231399999);
-}
-
-pub const Info = struct {
-    version: u8,
-};
-
-pub const diamond_info = Info{ .version = 0 };
-
-test "comptime modification of const struct field" {
-    comptime {
-        var res = diamond_info;
-        res.version = 1;
-        try expect(diamond_info.version == 0);
-        try expect(res.version == 1);
-    }
-}
-
 test "pointer to type" {
     comptime {
         var T: type = i32;
@@ -614,233 +125,8 @@ test "pointer to type" {
     }
 }
 
-test "slice of type" {
-    comptime {
-        var types_array = [_]type{ i32, f64, type };
-        for (types_array) |T, i| {
-            switch (i) {
-                0 => try expect(T == i32),
-                1 => try expect(T == f64),
-                2 => try expect(T == type),
-                else => unreachable,
-            }
-        }
-        for (types_array[0..]) |T, i| {
-            switch (i) {
-                0 => try expect(T == i32),
-                1 => try expect(T == f64),
-                2 => try expect(T == type),
-                else => unreachable,
-            }
-        }
-    }
-}
-
-const Wrapper = struct {
-    T: type,
-};
-
-fn wrap(comptime T: type) Wrapper {
-    return Wrapper{ .T = T };
-}
-
-test "function which returns struct with type field causes implicit comptime" {
-    const ty = wrap(i32).T;
-    try expect(ty == i32);
-}
-
-test "call method with comptime pass-by-non-copying-value self parameter" {
-    const S = struct {
-        a: u8,
-
-        fn b(comptime s: @This()) u8 {
-            return s.a;
-        }
-    };
-
-    const s = S{ .a = 2 };
-    var b = s.b();
-    try expect(b == 2);
-}
-
-test "@tagName of @typeInfo" {
-    const str = @tagName(@typeInfo(u8));
-    try expect(std.mem.eql(u8, str, "Int"));
-}
-
-test "setting backward branch quota just before a generic fn call" {
-    @setEvalBranchQuota(1001);
-    loopNTimes(1001);
-}
-
-fn loopNTimes(comptime n: usize) void {
-    comptime var i = 0;
-    inline while (i < n) : (i += 1) {}
-}
-
-test "variable inside inline loop that has different types on different iterations" {
-    try testVarInsideInlineLoop(.{ true, @as(u32, 42) });
-}
-
-fn testVarInsideInlineLoop(args: anytype) !void {
-    comptime var i = 0;
-    inline while (i < args.len) : (i += 1) {
-        const x = args[i];
-        if (i == 0) try expect(x);
-        if (i == 1) try expect(x == 42);
-    }
-}
-
-test "inline for with same type but different values" {
-    var res: usize = 0;
-    inline for ([_]type{ [2]u8, [1]u8, [2]u8 }) |T| {
-        var a: T = undefined;
-        res += a.len;
-    }
-    try expect(res == 5);
-}
-
-test "refer to the type of a generic function" {
-    const Func = fn (type) void;
-    const f: Func = doNothingWithType;
-    f(i32);
-}
-
-fn doNothingWithType(comptime T: type) void {
-    _ = T;
-}
-
-test "zero extend from u0 to u1" {
-    var zero_u0: u0 = 0;
-    var zero_u1: u1 = zero_u0;
-    try expect(zero_u1 == 0);
-}
-
-test "bit shift a u1" {
-    var x: u1 = 1;
-    var y = x << 0;
-    try expect(y == 1);
-}
-
-test "comptime pointer cast array and then slice" {
-    const array = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8 };
-
-    const ptrA: [*]const u8 = @ptrCast([*]const u8, &array);
-    const sliceA: []const u8 = ptrA[0..2];
-
-    const ptrB: [*]const u8 = &array;
-    const sliceB: []const u8 = ptrB[0..2];
-
-    try expect(sliceA[1] == 2);
-    try expect(sliceB[1] == 2);
-}
-
-test "slice bounds in comptime concatenation" {
-    const bs = comptime blk: {
-        const b = "........1........";
-        break :blk b[8..9];
-    };
-    const str = "" ++ bs;
-    try expect(str.len == 1);
-    try expect(std.mem.eql(u8, str, "1"));
-
-    const str2 = bs ++ "";
-    try expect(str2.len == 1);
-    try expect(std.mem.eql(u8, str2, "1"));
-}
-
-test "comptime bitwise operators" {
-    comptime {
-        try expect(3 & 1 == 1);
-        try expect(3 & -1 == 3);
-        try expect(-3 & -1 == -3);
-        try expect(3 | -1 == -1);
-        try expect(-3 | -1 == -1);
-        try expect(3 ^ -1 == -4);
-        try expect(-3 ^ -1 == 2);
-        try expect(~@as(i8, -1) == 0);
-        try expect(~@as(i128, -1) == 0);
-        try expect(18446744073709551615 & 18446744073709551611 == 18446744073709551611);
-        try expect(-18446744073709551615 & -18446744073709551611 == -18446744073709551615);
-        try expect(~@as(u128, 0) == 0xffffffffffffffffffffffffffffffff);
-    }
-}
-
-test "*align(1) u16 is the same as *align(1:0:2) u16" {
-    comptime {
-        try expect(*align(1:0:2) u16 == *align(1) u16);
-        try expect(*align(2:0:2) u16 == *u16);
-    }
-}
-
-test "array concatenation forces comptime" {
-    var a = oneItem(3) ++ oneItem(4);
-    try expect(std.mem.eql(i32, &a, &[_]i32{ 3, 4 }));
-}
-
-test "array multiplication forces comptime" {
-    var a = oneItem(3) ** scalar(2);
-    try expect(std.mem.eql(i32, &a, &[_]i32{ 3, 3 }));
-}
-
-fn oneItem(x: i32) [1]i32 {
-    return [_]i32{x};
-}
-
-fn scalar(x: u32) u32 {
-    return x;
-}
-
 test "no undeclared identifier error in unanalyzed branches" {
     if (false) {
         lol_this_doesnt_exist = nonsense;
     }
 }
-
-test "comptime assign int to optional int" {
-    comptime {
-        var x: ?i32 = null;
-        x = 2;
-        x.? *= 10;
-        try expectEqual(20, x.?);
-    }
-}
-
-test "return 0 from function that has u0 return type" {
-    const S = struct {
-        fn foo_zero() u0 {
-            return 0;
-        }
-    };
-    comptime {
-        if (S.foo_zero() != 0) {
-            @compileError("test failed");
-        }
-    }
-}
-
-test "two comptime calls with array default initialized to undefined" {
-    const S = struct {
-        const CrossTarget = struct {
-            dynamic_linker: DynamicLinker = DynamicLinker{},
-
-            pub fn parse() void {
-                var result: CrossTarget = .{};
-                result.getCpuArch();
-            }
-
-            pub fn getCpuArch(self: CrossTarget) void {
-                _ = self;
-            }
-        };
-
-        const DynamicLinker = struct {
-            buffer: [255]u8 = undefined,
-        };
-    };
-
-    comptime {
-        S.CrossTarget.parse();
-        S.CrossTarget.parse();
-    }
-}
test/behavior/eval_stage1.zig
@@ -0,0 +1,717 @@
+const std = @import("std");
+const expect = std.testing.expect;
+const expectEqual = std.testing.expectEqual;
+
+test "statically initialized list" {
+    try expect(static_point_list[0].x == 1);
+    try expect(static_point_list[0].y == 2);
+    try expect(static_point_list[1].x == 3);
+    try expect(static_point_list[1].y == 4);
+}
+const Point = struct {
+    x: i32,
+    y: i32,
+};
+const static_point_list = [_]Point{
+    makePoint(1, 2),
+    makePoint(3, 4),
+};
+fn makePoint(x: i32, y: i32) Point {
+    return Point{
+        .x = x,
+        .y = y,
+    };
+}
+
+test "static eval list init" {
+    try expect(static_vec3.data[2] == 1.0);
+    try expect(vec3(0.0, 0.0, 3.0).data[2] == 3.0);
+}
+const static_vec3 = vec3(0.0, 0.0, 1.0);
+pub const Vec3 = struct {
+    data: [3]f32,
+};
+pub fn vec3(x: f32, y: f32, z: f32) Vec3 {
+    return Vec3{
+        .data = [_]f32{
+            x,
+            y,
+            z,
+        },
+    };
+}
+
+test "constant struct with negation" {
+    try expect(vertices[0].x == -0.6);
+}
+const Vertex = struct {
+    x: f32,
+    y: f32,
+    r: f32,
+    g: f32,
+    b: f32,
+};
+const vertices = [_]Vertex{
+    Vertex{
+        .x = -0.6,
+        .y = -0.4,
+        .r = 1.0,
+        .g = 0.0,
+        .b = 0.0,
+    },
+    Vertex{
+        .x = 0.6,
+        .y = -0.4,
+        .r = 0.0,
+        .g = 1.0,
+        .b = 0.0,
+    },
+    Vertex{
+        .x = 0.0,
+        .y = 0.6,
+        .r = 0.0,
+        .g = 0.0,
+        .b = 1.0,
+    },
+};
+
+test "statically initialized struct" {
+    st_init_str_foo.x += 1;
+    try expect(st_init_str_foo.x == 14);
+}
+const StInitStrFoo = struct {
+    x: i32,
+    y: bool,
+};
+var st_init_str_foo = StInitStrFoo{
+    .x = 13,
+    .y = true,
+};
+
+test "statically initalized array literal" {
+    const y: [4]u8 = st_init_arr_lit_x;
+    try expect(y[3] == 4);
+}
+const st_init_arr_lit_x = [_]u8{
+    1,
+    2,
+    3,
+    4,
+};
+
+test "const slice" {
+    comptime {
+        const a = "1234567890";
+        try expect(a.len == 10);
+        const b = a[1..2];
+        try expect(b.len == 1);
+        try expect(b[0] == '2');
+    }
+}
+
+test "try to trick eval with runtime if" {
+    try expect(testTryToTrickEvalWithRuntimeIf(true) == 10);
+}
+
+fn testTryToTrickEvalWithRuntimeIf(b: bool) usize {
+    comptime var i: usize = 0;
+    inline while (i < 10) : (i += 1) {
+        const result = if (b) false else true;
+        _ = result;
+    }
+    comptime {
+        return i;
+    }
+}
+
+test "inlined loop has array literal with elided runtime scope on first iteration but not second iteration" {
+    var runtime = [1]i32{3};
+    comptime var i: usize = 0;
+    inline while (i < 2) : (i += 1) {
+        const result = if (i == 0) [1]i32{2} else runtime;
+        _ = result;
+    }
+    comptime {
+        try expect(i == 2);
+    }
+}
+
+const CmdFn = struct {
+    name: []const u8,
+    func: fn (i32) i32,
+};
+
+const cmd_fns = [_]CmdFn{
+    CmdFn{
+        .name = "one",
+        .func = one,
+    },
+    CmdFn{
+        .name = "two",
+        .func = two,
+    },
+    CmdFn{
+        .name = "three",
+        .func = three,
+    },
+};
+fn one(value: i32) i32 {
+    return value + 1;
+}
+fn two(value: i32) i32 {
+    return value + 2;
+}
+fn three(value: i32) i32 {
+    return value + 3;
+}
+
+fn performFn(comptime prefix_char: u8, start_value: i32) i32 {
+    var result: i32 = start_value;
+    comptime var i = 0;
+    inline while (i < cmd_fns.len) : (i += 1) {
+        if (cmd_fns[i].name[0] == prefix_char) {
+            result = cmd_fns[i].func(result);
+        }
+    }
+    return result;
+}
+
+test "comptime iterate over fn ptr list" {
+    try expect(performFn('t', 1) == 6);
+    try expect(performFn('o', 0) == 1);
+    try expect(performFn('w', 99) == 99);
+}
+
+test "eval @setFloatMode at compile-time" {
+    const result = comptime fnWithFloatMode();
+    try expect(result == 1234.0);
+}
+
+fn fnWithFloatMode() f32 {
+    @setFloatMode(std.builtin.FloatMode.Strict);
+    return 1234.0;
+}
+
+const SimpleStruct = struct {
+    field: i32,
+
+    fn method(self: *const SimpleStruct) i32 {
+        return self.field + 3;
+    }
+};
+
+var simple_struct = SimpleStruct{ .field = 1234 };
+
+const bound_fn = simple_struct.method;
+
+test "call method on bound fn referring to var instance" {
+    try expect(bound_fn() == 1237);
+}
+
+test "ptr to local array argument at comptime" {
+    comptime {
+        var bytes: [10]u8 = undefined;
+        modifySomeBytes(bytes[0..]);
+        try expect(bytes[0] == 'a');
+        try expect(bytes[9] == 'b');
+    }
+}
+
+fn modifySomeBytes(bytes: []u8) void {
+    bytes[0] = 'a';
+    bytes[9] = 'b';
+}
+
+test "comparisons 0 <= uint and 0 > uint should be comptime" {
+    testCompTimeUIntComparisons(1234);
+}
+fn testCompTimeUIntComparisons(x: u32) void {
+    if (!(0 <= x)) {
+        @compileError("this condition should be comptime known");
+    }
+    if (0 > x) {
+        @compileError("this condition should be comptime known");
+    }
+    if (!(x >= 0)) {
+        @compileError("this condition should be comptime known");
+    }
+    if (x < 0) {
+        @compileError("this condition should be comptime known");
+    }
+}
+
+test "const ptr to variable data changes at runtime" {
+    try expect(foo_ref.name[0] == 'a');
+    foo_ref.name = "b";
+    try expect(foo_ref.name[0] == 'b');
+}
+
+const Foo = struct {
+    name: []const u8,
+};
+
+var foo_contents = Foo{ .name = "a" };
+const foo_ref = &foo_contents;
+
+test "create global array with for loop" {
+    try expect(global_array[5] == 5 * 5);
+    try expect(global_array[9] == 9 * 9);
+}
+
+const global_array = x: {
+    var result: [10]usize = undefined;
+    for (result) |*item, index| {
+        item.* = index * index;
+    }
+    break :x result;
+};
+
+const hi1 = "hi";
+const hi2 = hi1;
+test "const global shares pointer with other same one" {
+    try assertEqualPtrs(&hi1[0], &hi2[0]);
+    comptime try expect(&hi1[0] == &hi2[0]);
+}
+fn assertEqualPtrs(ptr1: *const u8, ptr2: *const u8) !void {
+    try expect(ptr1 == ptr2);
+}
+
+test "@setEvalBranchQuota" {
+    comptime {
+        // 1001 for the loop and then 1 more for the expect fn call
+        @setEvalBranchQuota(1002);
+        var i = 0;
+        var sum = 0;
+        while (i < 1001) : (i += 1) {
+            sum += i;
+        }
+        try expect(sum == 500500);
+    }
+}
+
+test "float literal at compile time not lossy" {
+    try expect(16777216.0 + 1.0 == 16777217.0);
+    try expect(9007199254740992.0 + 1.0 == 9007199254740993.0);
+}
+
+test "f32 at compile time is lossy" {
+    try expect(@as(f32, 1 << 24) + 1 == 1 << 24);
+}
+
+test "f64 at compile time is lossy" {
+    try expect(@as(f64, 1 << 53) + 1 == 1 << 53);
+}
+
+test "f128 at compile time is lossy" {
+    try expect(@as(f128, 10384593717069655257060992658440192.0) + 1 == 10384593717069655257060992658440192.0);
+}
+
+test {
+    comptime try expect(@as(f128, 1 << 113) == 10384593717069655257060992658440192);
+}
+
+pub fn TypeWithCompTimeSlice(comptime field_name: []const u8) type {
+    _ = field_name;
+    return struct {
+        pub const Node = struct {};
+    };
+}
+
+test "string literal used as comptime slice is memoized" {
+    const a = "link";
+    const b = "link";
+    comptime try expect(TypeWithCompTimeSlice(a).Node == TypeWithCompTimeSlice(b).Node);
+    comptime try expect(TypeWithCompTimeSlice("link").Node == TypeWithCompTimeSlice("link").Node);
+}
+
+test "comptime slice of undefined pointer of length 0" {
+    const slice1 = @as([*]i32, undefined)[0..0];
+    try expect(slice1.len == 0);
+    const slice2 = @as([*]i32, undefined)[100..100];
+    try expect(slice2.len == 0);
+}
+
+fn copyWithPartialInline(s: []u32, b: []u8) void {
+    comptime var i: usize = 0;
+    inline while (i < 4) : (i += 1) {
+        s[i] = 0;
+        s[i] |= @as(u32, b[i * 4 + 0]) << 24;
+        s[i] |= @as(u32, b[i * 4 + 1]) << 16;
+        s[i] |= @as(u32, b[i * 4 + 2]) << 8;
+        s[i] |= @as(u32, b[i * 4 + 3]) << 0;
+    }
+}
+
+test "binary math operator in partially inlined function" {
+    var s: [4]u32 = undefined;
+    var b: [16]u8 = undefined;
+
+    for (b) |*r, i|
+        r.* = @intCast(u8, i + 1);
+
+    copyWithPartialInline(s[0..], b[0..]);
+    try expect(s[0] == 0x1020304);
+    try expect(s[1] == 0x5060708);
+    try expect(s[2] == 0x90a0b0c);
+    try expect(s[3] == 0xd0e0f10);
+}
+
+test "comptime function with the same args is memoized" {
+    comptime {
+        try expect(MakeType(i32) == MakeType(i32));
+        try expect(MakeType(i32) != MakeType(f64));
+    }
+}
+
+fn MakeType(comptime T: type) type {
+    return struct {
+        field: T,
+    };
+}
+
+test "comptime function with mutable pointer is not memoized" {
+    comptime {
+        var x: i32 = 1;
+        const ptr = &x;
+        increment(ptr);
+        increment(ptr);
+        try expect(x == 3);
+    }
+}
+
+fn increment(value: *i32) void {
+    value.* += 1;
+}
+
+fn generateTable(comptime T: type) [1010]T {
+    var res: [1010]T = undefined;
+    var i: usize = 0;
+    while (i < 1010) : (i += 1) {
+        res[i] = @intCast(T, i);
+    }
+    return res;
+}
+
+fn doesAlotT(comptime T: type, value: usize) T {
+    @setEvalBranchQuota(5000);
+    const table = comptime blk: {
+        break :blk generateTable(T);
+    };
+    return table[value];
+}
+
+test "@setEvalBranchQuota at same scope as generic function call" {
+    try expect(doesAlotT(u32, 2) == 2);
+}
+
+test "comptime slice of slice preserves comptime var" {
+    comptime {
+        var buff: [10]u8 = undefined;
+        buff[0..][0..][0] = 1;
+        try expect(buff[0..][0..][0] == 1);
+    }
+}
+
+test "comptime slice of pointer preserves comptime var" {
+    comptime {
+        var buff: [10]u8 = undefined;
+        var a = @ptrCast([*]u8, &buff);
+        a[0..1][0] = 1;
+        try expect(buff[0..][0..][0] == 1);
+    }
+}
+
+const SingleFieldStruct = struct {
+    x: i32,
+
+    fn read_x(self: *const SingleFieldStruct) i32 {
+        return self.x;
+    }
+};
+test "const ptr to comptime mutable data is not memoized" {
+    comptime {
+        var foo = SingleFieldStruct{ .x = 1 };
+        try expect(foo.read_x() == 1);
+        foo.x = 2;
+        try expect(foo.read_x() == 2);
+    }
+}
+
+test "array concat of slices gives slice" {
+    comptime {
+        var a: []const u8 = "aoeu";
+        var b: []const u8 = "asdf";
+        const c = a ++ b;
+        try expect(std.mem.eql(u8, c, "aoeuasdf"));
+    }
+}
+
+test "comptime shlWithOverflow" {
+    const ct_shifted: u64 = comptime amt: {
+        var amt = @as(u64, 0);
+        _ = @shlWithOverflow(u64, ~@as(u64, 0), 16, &amt);
+        break :amt amt;
+    };
+
+    const rt_shifted: u64 = amt: {
+        var amt = @as(u64, 0);
+        _ = @shlWithOverflow(u64, ~@as(u64, 0), 16, &amt);
+        break :amt amt;
+    };
+
+    try expect(ct_shifted == rt_shifted);
+}
+
+test "comptime shl" {
+    var a: u128 = 3;
+    var b: u7 = 63;
+    var c: u128 = 3 << 63;
+    try expectEqual(a << b, c);
+}
+
+test "runtime 128 bit integer division" {
+    var a: u128 = 152313999999999991610955792383;
+    var b: u128 = 10000000000000000000;
+    var c = a / b;
+    try expect(c == 15231399999);
+}
+
+pub const Info = struct {
+    version: u8,
+};
+
+pub const diamond_info = Info{ .version = 0 };
+
+test "comptime modification of const struct field" {
+    comptime {
+        var res = diamond_info;
+        res.version = 1;
+        try expect(diamond_info.version == 0);
+        try expect(res.version == 1);
+    }
+}
+
+test "slice of type" {
+    comptime {
+        var types_array = [_]type{ i32, f64, type };
+        for (types_array) |T, i| {
+            switch (i) {
+                0 => try expect(T == i32),
+                1 => try expect(T == f64),
+                2 => try expect(T == type),
+                else => unreachable,
+            }
+        }
+        for (types_array[0..]) |T, i| {
+            switch (i) {
+                0 => try expect(T == i32),
+                1 => try expect(T == f64),
+                2 => try expect(T == type),
+                else => unreachable,
+            }
+        }
+    }
+}
+
+const Wrapper = struct {
+    T: type,
+};
+
+fn wrap(comptime T: type) Wrapper {
+    return Wrapper{ .T = T };
+}
+
+test "function which returns struct with type field causes implicit comptime" {
+    const ty = wrap(i32).T;
+    try expect(ty == i32);
+}
+
+test "call method with comptime pass-by-non-copying-value self parameter" {
+    const S = struct {
+        a: u8,
+
+        fn b(comptime s: @This()) u8 {
+            return s.a;
+        }
+    };
+
+    const s = S{ .a = 2 };
+    var b = s.b();
+    try expect(b == 2);
+}
+
+test "@tagName of @typeInfo" {
+    const str = @tagName(@typeInfo(u8));
+    try expect(std.mem.eql(u8, str, "Int"));
+}
+
+test "setting backward branch quota just before a generic fn call" {
+    @setEvalBranchQuota(1001);
+    loopNTimes(1001);
+}
+
+fn loopNTimes(comptime n: usize) void {
+    comptime var i = 0;
+    inline while (i < n) : (i += 1) {}
+}
+
+test "variable inside inline loop that has different types on different iterations" {
+    try testVarInsideInlineLoop(.{ true, @as(u32, 42) });
+}
+
+fn testVarInsideInlineLoop(args: anytype) !void {
+    comptime var i = 0;
+    inline while (i < args.len) : (i += 1) {
+        const x = args[i];
+        if (i == 0) try expect(x);
+        if (i == 1) try expect(x == 42);
+    }
+}
+
+test "inline for with same type but different values" {
+    var res: usize = 0;
+    inline for ([_]type{ [2]u8, [1]u8, [2]u8 }) |T| {
+        var a: T = undefined;
+        res += a.len;
+    }
+    try expect(res == 5);
+}
+
+test "refer to the type of a generic function" {
+    const Func = fn (type) void;
+    const f: Func = doNothingWithType;
+    f(i32);
+}
+
+fn doNothingWithType(comptime T: type) void {
+    _ = T;
+}
+
+test "zero extend from u0 to u1" {
+    var zero_u0: u0 = 0;
+    var zero_u1: u1 = zero_u0;
+    try expect(zero_u1 == 0);
+}
+
+test "bit shift a u1" {
+    var x: u1 = 1;
+    var y = x << 0;
+    try expect(y == 1);
+}
+
+test "comptime pointer cast array and then slice" {
+    const array = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8 };
+
+    const ptrA: [*]const u8 = @ptrCast([*]const u8, &array);
+    const sliceA: []const u8 = ptrA[0..2];
+
+    const ptrB: [*]const u8 = &array;
+    const sliceB: []const u8 = ptrB[0..2];
+
+    try expect(sliceA[1] == 2);
+    try expect(sliceB[1] == 2);
+}
+
+test "slice bounds in comptime concatenation" {
+    const bs = comptime blk: {
+        const b = "........1........";
+        break :blk b[8..9];
+    };
+    const str = "" ++ bs;
+    try expect(str.len == 1);
+    try expect(std.mem.eql(u8, str, "1"));
+
+    const str2 = bs ++ "";
+    try expect(str2.len == 1);
+    try expect(std.mem.eql(u8, str2, "1"));
+}
+
+test "comptime bitwise operators" {
+    comptime {
+        try expect(3 & 1 == 1);
+        try expect(3 & -1 == 3);
+        try expect(-3 & -1 == -3);
+        try expect(3 | -1 == -1);
+        try expect(-3 | -1 == -1);
+        try expect(3 ^ -1 == -4);
+        try expect(-3 ^ -1 == 2);
+        try expect(~@as(i8, -1) == 0);
+        try expect(~@as(i128, -1) == 0);
+        try expect(18446744073709551615 & 18446744073709551611 == 18446744073709551611);
+        try expect(-18446744073709551615 & -18446744073709551611 == -18446744073709551615);
+        try expect(~@as(u128, 0) == 0xffffffffffffffffffffffffffffffff);
+    }
+}
+
+test "*align(1) u16 is the same as *align(1:0:2) u16" {
+    comptime {
+        try expect(*align(1:0:2) u16 == *align(1) u16);
+        try expect(*align(2:0:2) u16 == *u16);
+    }
+}
+
+test "array concatenation forces comptime" {
+    var a = oneItem(3) ++ oneItem(4);
+    try expect(std.mem.eql(i32, &a, &[_]i32{ 3, 4 }));
+}
+
+test "array multiplication forces comptime" {
+    var a = oneItem(3) ** scalar(2);
+    try expect(std.mem.eql(i32, &a, &[_]i32{ 3, 3 }));
+}
+
+fn oneItem(x: i32) [1]i32 {
+    return [_]i32{x};
+}
+
+fn scalar(x: u32) u32 {
+    return x;
+}
+
+test "comptime assign int to optional int" {
+    comptime {
+        var x: ?i32 = null;
+        x = 2;
+        x.? *= 10;
+        try expectEqual(20, x.?);
+    }
+}
+
+test "return 0 from function that has u0 return type" {
+    const S = struct {
+        fn foo_zero() u0 {
+            return 0;
+        }
+    };
+    comptime {
+        if (S.foo_zero() != 0) {
+            @compileError("test failed");
+        }
+    }
+}
+
+test "two comptime calls with array default initialized to undefined" {
+    const S = struct {
+        const CrossTarget = struct {
+            dynamic_linker: DynamicLinker = DynamicLinker{},
+
+            pub fn parse() void {
+                var result: CrossTarget = .{};
+                result.getCpuArch();
+            }
+
+            pub fn getCpuArch(self: CrossTarget) void {
+                _ = self;
+            }
+        };
+
+        const DynamicLinker = struct {
+            buffer: [255]u8 = undefined,
+        };
+    };
+
+    comptime {
+        S.CrossTarget.parse();
+        S.CrossTarget.parse();
+    }
+}
test/behavior.zig
@@ -5,6 +5,7 @@ test {
     _ = @import("behavior/bool.zig");
     _ = @import("behavior/basic.zig");
     _ = @import("behavior/generics.zig");
+    _ = @import("behavior/eval.zig");
 
     if (!builtin.zig_is_stage2) {
         // Tests that only pass for stage1.
@@ -88,7 +89,7 @@ test {
         _ = @import("behavior/enum.zig");
         _ = @import("behavior/enum_with_members.zig");
         _ = @import("behavior/error.zig");
-        _ = @import("behavior/eval.zig");
+        _ = @import("behavior/eval_stage1.zig");
         _ = @import("behavior/field_parent_ptr.zig");
         _ = @import("behavior/floatop.zig");
         _ = @import("behavior/fn.zig");