| ... | @@ -344,7 +344,9 @@ pub const Value = extern union { | ... | @@ -344,7 +344,9 @@ pub const Value = extern union { |
| 344 | return null; | 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 | if (self.tag_if_small_enough < Tag.no_payload_count) { | 350 | if (self.tag_if_small_enough < Tag.no_payload_count) { |
| 349 | return Value{ .tag_if_small_enough = self.tag_if_small_enough }; | 351 | return Value{ .tag_if_small_enough = self.tag_if_small_enough }; |
| 350 | } else switch (self.ptr_otherwise.tag) { | 352 | } else switch (self.ptr_otherwise.tag) { |
| ... | @@ -421,37 +423,37 @@ pub const Value = extern union { | ... | @@ -421,37 +423,37 @@ pub const Value = extern union { |
| 421 | | 423 | |
| 422 | .ty => { | 424 | .ty => { |
| 423 | const payload = self.castTag(.ty).?; | 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 | new_payload.* = .{ | 427 | new_payload.* = .{ |
| 426 | .base = payload.base, | 428 | .base = payload.base, |
| 427 | .data = try payload.data.copy(allocator), | 429 | .data = try payload.data.copy(arena), |
| 428 | }; | 430 | }; |
| 429 | return Value{ .ptr_otherwise = &new_payload.base }; | 431 | return Value{ .ptr_otherwise = &new_payload.base }; |
| 430 | }, | 432 | }, |
| 431 | .int_type => return self.copyPayloadShallow(allocator, Payload.IntType), | 433 | .int_type => return self.copyPayloadShallow(arena, Payload.IntType), |
| 432 | .int_u64 => return self.copyPayloadShallow(allocator, Payload.U64), | 434 | .int_u64 => return self.copyPayloadShallow(arena, Payload.U64), |
| 433 | .int_i64 => return self.copyPayloadShallow(allocator, Payload.I64), | 435 | .int_i64 => return self.copyPayloadShallow(arena, Payload.I64), |
| 434 | .int_big_positive, .int_big_negative => { | 436 | .int_big_positive, .int_big_negative => { |
| 435 | const old_payload = self.cast(Payload.BigInt).?; | 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 | new_payload.* = .{ | 439 | new_payload.* = .{ |
| 438 | .base = .{ .tag = self.ptr_otherwise.tag }, | 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 | return Value{ .ptr_otherwise = &new_payload.base }; | 443 | return Value{ .ptr_otherwise = &new_payload.base }; |
| 442 | }, | 444 | }, |
| 443 | .function => return self.copyPayloadShallow(allocator, Payload.Function), | 445 | .function => return self.copyPayloadShallow(arena, Payload.Function), |
| 444 | .extern_fn => return self.copyPayloadShallow(allocator, Payload.Decl), | 446 | .extern_fn => return self.copyPayloadShallow(arena, Payload.Decl), |
| 445 | .variable => return self.copyPayloadShallow(allocator, Payload.Variable), | 447 | .variable => return self.copyPayloadShallow(arena, Payload.Variable), |
| 446 | .decl_ref => return self.copyPayloadShallow(allocator, Payload.Decl), | 448 | .decl_ref => return self.copyPayloadShallow(arena, Payload.Decl), |
| 447 | .decl_ref_mut => return self.copyPayloadShallow(allocator, Payload.DeclRefMut), | 449 | .decl_ref_mut => return self.copyPayloadShallow(arena, Payload.DeclRefMut), |
| 448 | .elem_ptr => { | 450 | .elem_ptr => { |
| 449 | const payload = self.castTag(.elem_ptr).?; | 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 | new_payload.* = .{ | 453 | new_payload.* = .{ |
| 452 | .base = payload.base, | 454 | .base = payload.base, |
| 453 | .data = .{ | 455 | .data = .{ |
| 454 | .array_ptr = try payload.data.array_ptr.copy(allocator), | 456 | .array_ptr = try payload.data.array_ptr.copy(arena), |
| 455 | .index = payload.data.index, | 457 | .index = payload.data.index, |
| 456 | }, | 458 | }, |
| 457 | }; | 459 | }; |
| ... | @@ -459,17 +461,17 @@ pub const Value = extern union { | ... | @@ -459,17 +461,17 @@ pub const Value = extern union { |
| 459 | }, | 461 | }, |
| 460 | .field_ptr => { | 462 | .field_ptr => { |
| 461 | const payload = self.castTag(.field_ptr).?; | 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 | new_payload.* = .{ | 465 | new_payload.* = .{ |
| 464 | .base = payload.base, | 466 | .base = payload.base, |
| 465 | .data = .{ | 467 | .data = .{ |
| 466 | .container_ptr = try payload.data.container_ptr.copy(allocator), | 468 | .container_ptr = try payload.data.container_ptr.copy(arena), |
| 467 | .field_index = payload.data.field_index, | 469 | .field_index = payload.data.field_index, |
| 468 | }, | 470 | }, |
| 469 | }; | 471 | }; |
| 470 | return Value{ .ptr_otherwise = &new_payload.base }; | 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 | .repeated, | 475 | .repeated, |
| 474 | .eu_payload, | 476 | .eu_payload, |
| 475 | .eu_payload_ptr, | 477 | .eu_payload_ptr, |
| ... | @@ -477,61 +479,85 @@ pub const Value = extern union { | ... | @@ -477,61 +479,85 @@ pub const Value = extern union { |
| 477 | .opt_payload_ptr, | 479 | .opt_payload_ptr, |
| 478 | => { | 480 | => { |
| 479 | const payload = self.cast(Payload.SubValue).?; | 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 | new_payload.* = .{ | 483 | new_payload.* = .{ |
| 482 | .base = payload.base, | 484 | .base = payload.base, |
| 483 | .data = try payload.data.copy(allocator), | 485 | .data = try payload.data.copy(arena), |
| 484 | }; | 486 | }; |
| 485 | return Value{ .ptr_otherwise = &new_payload.base }; | 487 | return Value{ .ptr_otherwise = &new_payload.base }; |
| 486 | }, | 488 | }, |
| 487 | .array => { | 489 | .array => { |
| 488 | const payload = self.castTag(.array).?; | 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 | new_payload.* = .{ | 492 | new_payload.* = .{ |
| 491 | .base = payload.base, | 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 | std.mem.copy(Value, new_payload.data, payload.data); | 496 | std.mem.copy(Value, new_payload.data, payload.data); |
| 495 | return Value{ .ptr_otherwise = &new_payload.base }; | 497 | return Value{ .ptr_otherwise = &new_payload.base }; |
| 496 | }, | 498 | }, |
| 497 | .slice => { | 499 | .slice => { |
| 498 | const payload = self.castTag(.slice).?; | 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 | new_payload.* = .{ | 502 | new_payload.* = .{ |
| 501 | .base = payload.base, | 503 | .base = payload.base, |
| 502 | .data = .{ | 504 | .data = .{ |
| 503 | .ptr = try payload.data.ptr.copy(allocator), | 505 | .ptr = try payload.data.ptr.copy(arena), |
| 504 | .len = try payload.data.len.copy(allocator), | 506 | .len = try payload.data.len.copy(arena), |
| 505 | }, | 507 | }, |
| 506 | }; | 508 | }; |
| 507 | return Value{ .ptr_otherwise = &new_payload.base }; | 509 | return Value{ .ptr_otherwise = &new_payload.base }; |
| 508 | }, | 510 | }, |
| 509 | .float_16 => return self.copyPayloadShallow(allocator, Payload.Float_16), | 511 | .float_16 => return self.copyPayloadShallow(arena, Payload.Float_16), |
| 510 | .float_32 => return self.copyPayloadShallow(allocator, Payload.Float_32), | 512 | .float_32 => return self.copyPayloadShallow(arena, Payload.Float_32), |
| 511 | .float_64 => return self.copyPayloadShallow(allocator, Payload.Float_64), | 513 | .float_64 => return self.copyPayloadShallow(arena, Payload.Float_64), |
| 512 | .float_128 => return self.copyPayloadShallow(allocator, Payload.Float_128), | 514 | .float_128 => return self.copyPayloadShallow(arena, Payload.Float_128), |
| 513 | .enum_literal => { | 515 | .enum_literal => { |
| 514 | const payload = self.castTag(.enum_literal).?; | 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 | new_payload.* = .{ | 518 | new_payload.* = .{ |
| 517 | .base = payload.base, | 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 | return Value{ .ptr_otherwise = &new_payload.base }; | 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 | .inferred_alloc => unreachable, | 553 | .inferred_alloc => unreachable, |
| 528 | .inferred_alloc_comptime => unreachable, | 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 | const payload = self.cast(T).?; | 559 | const payload = self.cast(T).?; |
| 534 | const new_payload = try allocator.create(T); | 560 | const new_payload = try arena.create(T); |
| 535 | new_payload.* = payload.*; | 561 | new_payload.* = payload.*; |
| 536 | return Value{ .ptr_otherwise = &new_payload.base }; | 562 | return Value{ .ptr_otherwise = &new_payload.base }; |
| 537 | } | 563 | } |
| ... | @@ -1932,8 +1958,9 @@ pub const Value = extern union { | ... | @@ -1932,8 +1958,9 @@ pub const Value = extern union { |
| 1932 | pub const base_tag = Tag.@"struct"; | 1958 | pub const base_tag = Tag.@"struct"; |
| 1933 | | 1959 | |
| 1934 | base: Payload = .{ .tag = base_tag }, | 1960 | base: Payload = .{ .tag = base_tag }, |
| 1935 | /// Field values. The number and type are according to the struct type. | 1961 | /// Field values. The types are according to the struct type. |
| 1936 | data: [*]Value, | 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 | pub const Union = struct { | 1966 | pub const Union = struct { |