| ... | ... | @@ -344,7 +344,9 @@ pub const Value = extern union { |
| 344 | 344 | return null; |
| 345 | 345 | } |
| 346 | 346 | |
| 347 | | pub fn copy(self: Value, allocator: *Allocator) error{OutOfMemory}!Value { |
| 347 | /// It's intentional that this function is not passed a corresponding Type, so that |
| 348 | /// a Value can be copied from a Sema to a Decl prior to resolving struct/union field types. |
| 349 | pub fn copy(self: Value, arena: *Allocator) error{OutOfMemory}!Value { |
| 348 | 350 | if (self.tag_if_small_enough < Tag.no_payload_count) { |
| 349 | 351 | return Value{ .tag_if_small_enough = self.tag_if_small_enough }; |
| 350 | 352 | } else switch (self.ptr_otherwise.tag) { |
| ... | ... | @@ -421,37 +423,37 @@ pub const Value = extern union { |
| 421 | 423 | |
| 422 | 424 | .ty => { |
| 423 | 425 | const payload = self.castTag(.ty).?; |
| 424 | | const new_payload = try allocator.create(Payload.Ty); |
| 426 | const new_payload = try arena.create(Payload.Ty); |
| 425 | 427 | new_payload.* = .{ |
| 426 | 428 | .base = payload.base, |
| 427 | | .data = try payload.data.copy(allocator), |
| 429 | .data = try payload.data.copy(arena), |
| 428 | 430 | }; |
| 429 | 431 | return Value{ .ptr_otherwise = &new_payload.base }; |
| 430 | 432 | }, |
| 431 | | .int_type => return self.copyPayloadShallow(allocator, Payload.IntType), |
| 432 | | .int_u64 => return self.copyPayloadShallow(allocator, Payload.U64), |
| 433 | | .int_i64 => return self.copyPayloadShallow(allocator, Payload.I64), |
| 433 | .int_type => return self.copyPayloadShallow(arena, Payload.IntType), |
| 434 | .int_u64 => return self.copyPayloadShallow(arena, Payload.U64), |
| 435 | .int_i64 => return self.copyPayloadShallow(arena, Payload.I64), |
| 434 | 436 | .int_big_positive, .int_big_negative => { |
| 435 | 437 | const old_payload = self.cast(Payload.BigInt).?; |
| 436 | | const new_payload = try allocator.create(Payload.BigInt); |
| 438 | const new_payload = try arena.create(Payload.BigInt); |
| 437 | 439 | new_payload.* = .{ |
| 438 | 440 | .base = .{ .tag = self.ptr_otherwise.tag }, |
| 439 | | .data = try allocator.dupe(std.math.big.Limb, old_payload.data), |
| 441 | .data = try arena.dupe(std.math.big.Limb, old_payload.data), |
| 440 | 442 | }; |
| 441 | 443 | return Value{ .ptr_otherwise = &new_payload.base }; |
| 442 | 444 | }, |
| 443 | | .function => return self.copyPayloadShallow(allocator, Payload.Function), |
| 444 | | .extern_fn => return self.copyPayloadShallow(allocator, Payload.Decl), |
| 445 | | .variable => return self.copyPayloadShallow(allocator, Payload.Variable), |
| 446 | | .decl_ref => return self.copyPayloadShallow(allocator, Payload.Decl), |
| 447 | | .decl_ref_mut => return self.copyPayloadShallow(allocator, Payload.DeclRefMut), |
| 445 | .function => return self.copyPayloadShallow(arena, Payload.Function), |
| 446 | .extern_fn => return self.copyPayloadShallow(arena, Payload.Decl), |
| 447 | .variable => return self.copyPayloadShallow(arena, Payload.Variable), |
| 448 | .decl_ref => return self.copyPayloadShallow(arena, Payload.Decl), |
| 449 | .decl_ref_mut => return self.copyPayloadShallow(arena, Payload.DeclRefMut), |
| 448 | 450 | .elem_ptr => { |
| 449 | 451 | const payload = self.castTag(.elem_ptr).?; |
| 450 | | const new_payload = try allocator.create(Payload.ElemPtr); |
| 452 | const new_payload = try arena.create(Payload.ElemPtr); |
| 451 | 453 | new_payload.* = .{ |
| 452 | 454 | .base = payload.base, |
| 453 | 455 | .data = .{ |
| 454 | | .array_ptr = try payload.data.array_ptr.copy(allocator), |
| 456 | .array_ptr = try payload.data.array_ptr.copy(arena), |
| 455 | 457 | .index = payload.data.index, |
| 456 | 458 | }, |
| 457 | 459 | }; |
| ... | ... | @@ -459,17 +461,17 @@ pub const Value = extern union { |
| 459 | 461 | }, |
| 460 | 462 | .field_ptr => { |
| 461 | 463 | const payload = self.castTag(.field_ptr).?; |
| 462 | | const new_payload = try allocator.create(Payload.FieldPtr); |
| 464 | const new_payload = try arena.create(Payload.FieldPtr); |
| 463 | 465 | new_payload.* = .{ |
| 464 | 466 | .base = payload.base, |
| 465 | 467 | .data = .{ |
| 466 | | .container_ptr = try payload.data.container_ptr.copy(allocator), |
| 468 | .container_ptr = try payload.data.container_ptr.copy(arena), |
| 467 | 469 | .field_index = payload.data.field_index, |
| 468 | 470 | }, |
| 469 | 471 | }; |
| 470 | 472 | return Value{ .ptr_otherwise = &new_payload.base }; |
| 471 | 473 | }, |
| 472 | | .bytes => return self.copyPayloadShallow(allocator, Payload.Bytes), |
| 474 | .bytes => return self.copyPayloadShallow(arena, Payload.Bytes), |
| 473 | 475 | .repeated, |
| 474 | 476 | .eu_payload, |
| 475 | 477 | .eu_payload_ptr, |
| ... | ... | @@ -477,61 +479,85 @@ pub const Value = extern union { |
| 477 | 479 | .opt_payload_ptr, |
| 478 | 480 | => { |
| 479 | 481 | const payload = self.cast(Payload.SubValue).?; |
| 480 | | const new_payload = try allocator.create(Payload.SubValue); |
| 482 | const new_payload = try arena.create(Payload.SubValue); |
| 481 | 483 | new_payload.* = .{ |
| 482 | 484 | .base = payload.base, |
| 483 | | .data = try payload.data.copy(allocator), |
| 485 | .data = try payload.data.copy(arena), |
| 484 | 486 | }; |
| 485 | 487 | return Value{ .ptr_otherwise = &new_payload.base }; |
| 486 | 488 | }, |
| 487 | 489 | .array => { |
| 488 | 490 | const payload = self.castTag(.array).?; |
| 489 | | const new_payload = try allocator.create(Payload.Array); |
| 491 | const new_payload = try arena.create(Payload.Array); |
| 490 | 492 | new_payload.* = .{ |
| 491 | 493 | .base = payload.base, |
| 492 | | .data = try allocator.alloc(Value, payload.data.len), |
| 494 | .data = try arena.alloc(Value, payload.data.len), |
| 493 | 495 | }; |
| 494 | 496 | std.mem.copy(Value, new_payload.data, payload.data); |
| 495 | 497 | return Value{ .ptr_otherwise = &new_payload.base }; |
| 496 | 498 | }, |
| 497 | 499 | .slice => { |
| 498 | 500 | const payload = self.castTag(.slice).?; |
| 499 | | const new_payload = try allocator.create(Payload.Slice); |
| 501 | const new_payload = try arena.create(Payload.Slice); |
| 500 | 502 | new_payload.* = .{ |
| 501 | 503 | .base = payload.base, |
| 502 | 504 | .data = .{ |
| 503 | | .ptr = try payload.data.ptr.copy(allocator), |
| 504 | | .len = try payload.data.len.copy(allocator), |
| 505 | .ptr = try payload.data.ptr.copy(arena), |
| 506 | .len = try payload.data.len.copy(arena), |
| 505 | 507 | }, |
| 506 | 508 | }; |
| 507 | 509 | return Value{ .ptr_otherwise = &new_payload.base }; |
| 508 | 510 | }, |
| 509 | | .float_16 => return self.copyPayloadShallow(allocator, Payload.Float_16), |
| 510 | | .float_32 => return self.copyPayloadShallow(allocator, Payload.Float_32), |
| 511 | | .float_64 => return self.copyPayloadShallow(allocator, Payload.Float_64), |
| 512 | | .float_128 => return self.copyPayloadShallow(allocator, Payload.Float_128), |
| 511 | .float_16 => return self.copyPayloadShallow(arena, Payload.Float_16), |
| 512 | .float_32 => return self.copyPayloadShallow(arena, Payload.Float_32), |
| 513 | .float_64 => return self.copyPayloadShallow(arena, Payload.Float_64), |
| 514 | .float_128 => return self.copyPayloadShallow(arena, Payload.Float_128), |
| 513 | 515 | .enum_literal => { |
| 514 | 516 | const payload = self.castTag(.enum_literal).?; |
| 515 | | const new_payload = try allocator.create(Payload.Bytes); |
| 517 | const new_payload = try arena.create(Payload.Bytes); |
| 516 | 518 | new_payload.* = .{ |
| 517 | 519 | .base = payload.base, |
| 518 | | .data = try allocator.dupe(u8, payload.data), |
| 520 | .data = try arena.dupe(u8, payload.data), |
| 521 | }; |
| 522 | return Value{ .ptr_otherwise = &new_payload.base }; |
| 523 | }, |
| 524 | .enum_field_index => return self.copyPayloadShallow(arena, Payload.U32), |
| 525 | .@"error" => return self.copyPayloadShallow(arena, Payload.Error), |
| 526 | |
| 527 | .@"struct" => { |
| 528 | const old_field_values = self.castTag(.@"struct").?.data; |
| 529 | const new_payload = try arena.create(Payload.Struct); |
| 530 | new_payload.* = .{ |
| 531 | .base = .{ .tag = .@"struct" }, |
| 532 | .data = try arena.alloc(Value, old_field_values.len), |
| 533 | }; |
| 534 | for (old_field_values) |old_field_val, i| { |
| 535 | new_payload.data[i] = try old_field_val.copy(arena); |
| 536 | } |
| 537 | return Value{ .ptr_otherwise = &new_payload.base }; |
| 538 | }, |
| 539 | |
| 540 | .@"union" => { |
| 541 | const tag_and_val = self.castTag(.@"union").?.data; |
| 542 | const new_payload = try arena.create(Payload.Union); |
| 543 | new_payload.* = .{ |
| 544 | .base = .{ .tag = .@"union" }, |
| 545 | .data = .{ |
| 546 | .tag = try tag_and_val.tag.copy(arena), |
| 547 | .val = try tag_and_val.val.copy(arena), |
| 548 | }, |
| 519 | 549 | }; |
| 520 | 550 | return Value{ .ptr_otherwise = &new_payload.base }; |
| 521 | 551 | }, |
| 522 | | .enum_field_index => return self.copyPayloadShallow(allocator, Payload.U32), |
| 523 | | .@"error" => return self.copyPayloadShallow(allocator, Payload.Error), |
| 524 | | .@"struct" => @panic("TODO can't copy struct value without knowing the type"), |
| 525 | | .@"union" => @panic("TODO can't copy union value without knowing the type"), |
| 526 | 552 | |
| 527 | 553 | .inferred_alloc => unreachable, |
| 528 | 554 | .inferred_alloc_comptime => unreachable, |
| 529 | 555 | } |
| 530 | 556 | } |
| 531 | 557 | |
| 532 | | fn copyPayloadShallow(self: Value, allocator: *Allocator, comptime T: type) error{OutOfMemory}!Value { |
| 558 | fn copyPayloadShallow(self: Value, arena: *Allocator, comptime T: type) error{OutOfMemory}!Value { |
| 533 | 559 | const payload = self.cast(T).?; |
| 534 | | const new_payload = try allocator.create(T); |
| 560 | const new_payload = try arena.create(T); |
| 535 | 561 | new_payload.* = payload.*; |
| 536 | 562 | return Value{ .ptr_otherwise = &new_payload.base }; |
| 537 | 563 | } |
| ... | ... | @@ -1932,8 +1958,9 @@ pub const Value = extern union { |
| 1932 | 1958 | pub const base_tag = Tag.@"struct"; |
| 1933 | 1959 | |
| 1934 | 1960 | base: Payload = .{ .tag = base_tag }, |
| 1935 | | /// Field values. The number and type are according to the struct type. |
| 1936 | | data: [*]Value, |
| 1961 | /// Field values. The types are according to the struct type. |
| 1962 | /// The length is provided here so that copying a Value does not depend on the Type. |
| 1963 | data: []Value, |
| 1937 | 1964 | }; |
| 1938 | 1965 | |
| 1939 | 1966 | pub const Union = struct { |