| author | |
| committer | |
| log | ee6d161658572b76eb31d23be33043f63be4f556 |
| tree | 078a9377345cb661d277516ae79713dee297279d |
| parent | 9c9f440794d6c700dbbcf7bc410d954c694a36c1 |
| signature | Commit is signed but in an unrecognized format. |
these pointers get invalidated after appends to InternPool, so they
should store `Store.Slice(T)` instead. this introduces a memory leak
since there is a genuine use case for using real slices (when the query
is not in InternPool), but the fix for this is more convoluted and will
be done later when some other InternPool organization is done.14 files changed, 373 insertions(+), 301 deletions(-)
CHANGELOG.md+1| ... | @@ -11,6 +11,7 @@ | ... | @@ -11,6 +11,7 @@ |
| 11 | - fix: coerce `break` operands and implicit breaks to result type | 11 | - fix: coerce `break` operands and implicit breaks to result type |
| 12 | - fix: coerce results when `if` expression branches merge | 12 | - fix: coerce results when `if` expression branches merge |
| 13 | - fix: ensure if branch results to a runtime value when the condition is not compile-time known | 13 | - fix: ensure if branch results to a runtime value when the condition is not compile-time known |
| 14 | - fix: coerce return value to a runtime value | ||
| 14 | - fix: inferred array type uses item type for items instead of the container type. | 15 | - fix: inferred array type uses item type for items instead of the container type. |
| 15 | - fix(js): stop printing redundant parenthesis on ternary expressions | 16 | - fix(js): stop printing redundant parenthesis on ternary expressions |
| 16 | 17 |
README.md+2-2| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | # Ix | 1 | # Ix |
| 2 | 2 | ||
| 3 | Ix (`I`nferable E`x`pression) is a high-level, general purpose programming | 3 | Ix (*I*nferable E*x*pression) is a high-level, general purpose programming |
| 4 | language. It features a mix of Rust, Zig, and JavaScript's great points. | 4 | language. It features a mix of Rust, Zig, and JavaScript's great points. |
| 5 | 5 | ||
| 6 | For a guide on how to use Ix, see the manual included in the binary | 6 | For a guide on how to use Ix, see the manual included in the binary |
| ... | @@ -29,6 +29,6 @@ CLI to check spelling mistakes and [`dprint`][dprint] for code formatting. It is | ... | @@ -29,6 +29,6 @@ CLI to check spelling mistakes and [`dprint`][dprint] for code formatting. It is |
| 29 | recommended to setup editor integration with these two tools to prevent pushing | 29 | recommended to setup editor integration with these two tools to prevent pushing |
| 30 | broken commits. | 30 | broken commits. |
| 31 | 31 | ||
| 32 | [ci]: https://buildkite.com/paperdave/compiler | 32 | [ci]: https://buildkite.com/paperclover/compiler |
| 33 | [typos]: https://github.com/crate-ci/typos | 33 | [typos]: https://github.com/crate-ci/typos |
| 34 | [dprint]: https://dprint.dev | 34 | [dprint]: https://dprint.dev |
ci+16-14| ... | @@ -12,25 +12,27 @@ commit_short=$(echo "$commit" | cut -c -9) | ... | @@ -12,25 +12,27 @@ commit_short=$(echo "$commit" | cut -c -9) |
| 12 | typos | 12 | typos |
| 13 | dprint check | 13 | dprint check |
| 14 | 14 | ||
| 15 | if [ -n "$BUILDKITE" ]; then | 15 | if [ -n "$BUILDKITE" ] || [ "$1" == "all" ]; then |
| 16 | # perform the entire build | 16 | # perform the entire build |
| 17 | ./build all --summary all | 17 | ./build all --summary all |
| 18 | 18 | ||
| 19 | pushd zig-out/package | 19 | if [ -n "$BUILDKITE" ]; then |
| 20 | zip -r compiler-$commit.zip * | 20 | pushd zig-out/package |
| 21 | buildkite-agent artifact upload compiler-$commit.zip | 21 | zip -r compiler-$commit.zip * |
| 22 | popd | 22 | buildkite-agent artifact upload compiler-$commit.zip |
| 23 | popd | ||
| 23 | 24 | ||
| 24 | rm -fr zig-out/site | 25 | rm -fr zig-out/site |
| 25 | mkdir zig-out/site | 26 | mkdir zig-out/site |
| 26 | cp zig-out/package/ix.html zig-out/site/index.html | 27 | cp zig-out/package/ix.html zig-out/site/index.html |
| 27 | branch="$BUILDKITE_BRANCH" | 28 | branch="$BUILDKITE_BRANCH" |
| 28 | if [ "$branch" = "dev" ]; then | 29 | if [ "$branch" = "dev" ]; then |
| 29 | branch=main | 30 | branch=main |
| 31 | fi | ||
| 32 | CLOUDFLARE_API_TOKEN="$(buildkite-agent secret get CLOUDFLARE_API_TOKEN)" \ | ||
| 33 | CLOUDFLARE_ACCOUNT_ID="$(buildkite-agent secret get CLOUDFLARE_ACCOUNT_ID)" \ | ||
| 34 | wrangler pages deploy zig-out/site --branch "$branch" --commit-hash "$commit" --no-bundle --project-name language-manual | ||
| 30 | fi | 35 | fi |
| 31 | CLOUDFLARE_API_TOKEN="$(buildkite-agent secret get CLOUDFLARE_API_TOKEN)" \ | ||
| 32 | CLOUDFLARE_ACCOUNT_ID="$(buildkite-agent secret get CLOUDFLARE_ACCOUNT_ID)" \ | ||
| 33 | wrangler pages deploy zig-out/site --branch "$branch" --commit-hash "$commit" --no-bundle --project-name language-manual | ||
| 34 | else | 36 | else |
| 35 | # perform only the tests, with a shorter summary | 37 | # perform only the tests, with a shorter summary |
| 36 | ./build test --summary new | 38 | ./build test --summary new |
doc/language-manual.md+2-2| ... | @@ -179,7 +179,7 @@ it cannot be assigned to a `var` without an explicit type annotation. Since | ... | @@ -179,7 +179,7 @@ it cannot be assigned to a `var` without an explicit type annotation. Since |
| 179 | float, but a compiler warning will be emitted. | 179 | float, but a compiler warning will be emitted. |
| 180 | 180 | ||
| 181 | ```lang | 181 | ```lang |
| 182 | var number = 0; // `number` is a `float`, but not explicit | 182 | var number = 0; // `number` is `float`, but not explicit |
| 183 | var number: int = 0; // `number` is `int` | 183 | var number: int = 0; // `number` is `int` |
| 184 | var number: float = 0; // `number` is `float` | 184 | var number: float = 0; // `number` is `float` |
| 185 | ``` | 185 | ``` |
| ... | @@ -203,7 +203,7 @@ fn main { | ... | @@ -203,7 +203,7 @@ fn main { |
| 203 | 203 | ||
| 204 | The `return` expression can be used within functions to return early. | 204 | The `return` expression can be used within functions to return early. |
| 205 | 205 | ||
| 206 | ```lang:run | 206 | ```lang |
| 207 | let print = @extern("console").log; | 207 | let print = @extern("console").log; |
| 208 | 208 | ||
| 209 | fn something(a: int) -> bool { | 209 | fn something(a: int) -> bool { |
src/core/Air.Dump.zig+15-14| ... | @@ -52,7 +52,7 @@ pub const State = struct { | ... | @@ -52,7 +52,7 @@ pub const State = struct { |
| 52 | switch (tag) { | 52 | switch (tag) { |
| 53 | .block => { | 53 | .block => { |
| 54 | const index_list: Air.IndexList = air.instData(.block, inst); | 54 | const index_list: Air.IndexList = air.instData(.block, inst); |
| 55 | const insts = index_list.slice(air); | 55 | const insts = index_list.get(air); |
| 56 | try s.dumpInstList(w, insts, '{', '}'); | 56 | try s.dumpInstList(w, insts, '{', '}'); |
| 57 | }, | 57 | }, |
| 58 | .arg => { | 58 | .arg => { |
| ... | @@ -127,7 +127,7 @@ pub const State = struct { | ... | @@ -127,7 +127,7 @@ pub const State = struct { |
| 127 | air | 127 | air |
| 128 | .typeOfIndex(field.base, s.ip) | 128 | .typeOfIndex(field.base, s.ip) |
| 129 | .toStructType(s.ip).? | 129 | .toStructType(s.ip).? |
| 130 | .field_keys[field.field_index] | 130 | .field_keys.at(s.ip, field.field_index) |
| 131 | .toSlice(s.ip), | 131 | .toSlice(s.ip), |
| 132 | }); | 132 | }); |
| 133 | try tty.setColor(w, .reset); | 133 | try tty.setColor(w, .reset); |
| ... | @@ -149,7 +149,7 @@ pub const State = struct { | ... | @@ -149,7 +149,7 @@ pub const State = struct { |
| 149 | try w.writeAll("("); | 149 | try w.writeAll("("); |
| 150 | try s.dumpRef(w, call.base); | 150 | try s.dumpRef(w, call.base); |
| 151 | try w.writeAll(", "); | 151 | try w.writeAll(", "); |
| 152 | try s.dumpRefList(w, call_data.args.slice(air), '[', ']'); | 152 | try s.dumpRefList(w, call_data.args.get(air), '[', ']'); |
| 153 | try w.writeAll(")"); | 153 | try w.writeAll(")"); |
| 154 | }, | 154 | }, |
| 155 | .@"if" => { | 155 | .@"if" => { |
| ... | @@ -177,7 +177,7 @@ pub const State = struct { | ... | @@ -177,7 +177,7 @@ pub const State = struct { |
| 177 | try s.dumpValue(w, struct_init.ty.value()); | 177 | try s.dumpValue(w, struct_init.ty.value()); |
| 178 | try w.writeAll(", {"); | 178 | try w.writeAll(", {"); |
| 179 | s.indent += 1; | 179 | s.indent += 1; |
| 180 | for (struct_type.field_keys, struct_init.valuesPtr(air)) |key, ref| { | 180 | for (struct_type.field_keys.get(s.ip), struct_init.valuesPtr(air)) |key, ref| { |
| 181 | try s.newline(w); | 181 | try s.newline(w); |
| 182 | try w.print("{}: ", .{key.fmt(s.ip)}); | 182 | try w.print("{}: ", .{key.fmt(s.ip)}); |
| 183 | try s.dumpRef(w, ref); | 183 | try s.dumpRef(w, ref); |
| ... | @@ -192,7 +192,7 @@ pub const State = struct { | ... | @@ -192,7 +192,7 @@ pub const State = struct { |
| 192 | 192 | ||
| 193 | try w.writeAll("("); | 193 | try w.writeAll("("); |
| 194 | try s.dumpValue(w, array_type.item_type.value()); | 194 | try s.dumpValue(w, array_type.item_type.value()); |
| 195 | try s.dumpRefList(w, array_init.list.get(air).slice(air), '[', ']'); | 195 | try s.dumpRefList(w, array_init.list.get(air).get(air), '[', ']'); |
| 196 | try w.writeAll(")"); | 196 | try w.writeAll(")"); |
| 197 | }, | 197 | }, |
| 198 | .tuple_init => { | 198 | .tuple_init => { |
| ... | @@ -203,6 +203,7 @@ pub const State = struct { | ... | @@ -203,6 +203,7 @@ pub const State = struct { |
| 203 | // try s.dumpValue(w, array_type.item_type.value()); | 203 | // try s.dumpValue(w, array_type.item_type.value()); |
| 204 | // try s.dumpRefList(w, array_init.list.get(air).slice(air), '[', ']'); | 204 | // try s.dumpRefList(w, array_init.list.get(air).slice(air), '[', ']'); |
| 205 | // try w.writeAll(")"); | 205 | // try w.writeAll(")"); |
| 206 | @panic("TODO"); | ||
| 206 | }, | 207 | }, |
| 207 | } | 208 | } |
| 208 | } | 209 | } |
| ... | @@ -244,7 +245,7 @@ pub const State = struct { | ... | @@ -244,7 +245,7 @@ pub const State = struct { |
| 244 | try tty.setColor(w, .blue); | 245 | try tty.setColor(w, .blue); |
| 245 | try w.writeAll("fn("); | 246 | try w.writeAll("fn("); |
| 246 | try tty.setColor(w, .reset); | 247 | try tty.setColor(w, .reset); |
| 247 | for (ty.param_types, 0..) |param, i| { | 248 | for (ty.param_types.get(s.ip), 0..) |param, i| { |
| 248 | if (i != 0) { | 249 | if (i != 0) { |
| 249 | try tty.setColor(w, .blue); | 250 | try tty.setColor(w, .blue); |
| 250 | try w.writeAll(", "); | 251 | try w.writeAll(", "); |
| ... | @@ -322,8 +323,8 @@ pub const State = struct { | ... | @@ -322,8 +323,8 @@ pub const State = struct { |
| 322 | try w.writeAll(" "); | 323 | try w.writeAll(" "); |
| 323 | 324 | ||
| 324 | for ( | 325 | for ( |
| 325 | struct_type.field_keys, | 326 | struct_type.field_keys.get(s.ip), |
| 326 | struct_type.field_types, | 327 | struct_type.field_types.get(s.ip), |
| 327 | 0.., | 328 | 0.., |
| 328 | ) |key, field_type, i| { | 329 | ) |key, field_type, i| { |
| 329 | if (i != 0) | 330 | if (i != 0) |
| ... | @@ -352,8 +353,8 @@ pub const State = struct { | ... | @@ -352,8 +353,8 @@ pub const State = struct { |
| 352 | try w.writeAll(" "); | 353 | try w.writeAll(" "); |
| 353 | 354 | ||
| 354 | for ( | 355 | for ( |
| 355 | struct_value.ty.toStructType(s.ip).?.field_keys, | 356 | struct_value.ty.toStructType(s.ip).?.field_keys.get(s.ip), |
| 356 | struct_value.field_values, | 357 | struct_value.field_values.get(s.ip), |
| 357 | 0.., | 358 | 0.., |
| 358 | ) |key, value, i| { | 359 | ) |key, value, i| { |
| 359 | if (i != 0) | 360 | if (i != 0) |
| ... | @@ -385,7 +386,7 @@ pub const State = struct { | ... | @@ -385,7 +386,7 @@ pub const State = struct { |
| 385 | try tty.setColor(w, .reset); | 386 | try tty.setColor(w, .reset); |
| 386 | try w.writeAll("["); | 387 | try w.writeAll("["); |
| 387 | 388 | ||
| 388 | for (array_value.items, 0..) |value, i| { | 389 | for (array_value.items.get(s.ip), 0..) |value, i| { |
| 389 | if (i != 0) | 390 | if (i != 0) |
| 390 | try w.writeAll(", "); | 391 | try w.writeAll(", "); |
| 391 | try s.dumpValue(w, value); | 392 | try s.dumpValue(w, value); |
| ... | @@ -398,7 +399,7 @@ pub const State = struct { | ... | @@ -398,7 +399,7 @@ pub const State = struct { |
| 398 | }, | 399 | }, |
| 399 | .external_value => |external_value| { | 400 | .external_value => |external_value| { |
| 400 | try w.writeAll("external '"); | 401 | try w.writeAll("external '"); |
| 401 | for (external_value.key, 0..) |part, i| { | 402 | for (external_value.key.get(s.ip), 0..) |part, i| { |
| 402 | if (i != 0) try w.writeAll("."); | 403 | if (i != 0) try w.writeAll("."); |
| 403 | try w.writeAll(part.toSlice(s.ip)); | 404 | try w.writeAll(part.toSlice(s.ip)); |
| 404 | } | 405 | } |
| ... | @@ -406,7 +407,7 @@ pub const State = struct { | ... | @@ -406,7 +407,7 @@ pub const State = struct { |
| 406 | }, | 407 | }, |
| 407 | .tuple_type => |tuple_type| { | 408 | .tuple_type => |tuple_type| { |
| 408 | try w.writeAll("("); | 409 | try w.writeAll("("); |
| 409 | for (tuple_type.items, 0..) |item, i| { | 410 | for (tuple_type.items.get(s.ip), 0..) |item, i| { |
| 410 | if (i != 0) try w.writeAll(", "); | 411 | if (i != 0) try w.writeAll(", "); |
| 411 | try s.dumpValue(w, item.value()); | 412 | try s.dumpValue(w, item.value()); |
| 412 | } | 413 | } |
| ... | @@ -414,7 +415,7 @@ pub const State = struct { | ... | @@ -414,7 +415,7 @@ pub const State = struct { |
| 414 | }, | 415 | }, |
| 415 | .tuple_value => |tuple_value| { | 416 | .tuple_value => |tuple_value| { |
| 416 | try w.writeAll("("); | 417 | try w.writeAll("("); |
| 417 | for (tuple_value.items, 0..) |item, i| { | 418 | for (tuple_value.items.get(s.ip), 0..) |item, i| { |
| 418 | if (i != 0) try w.writeAll(", "); | 419 | if (i != 0) try w.writeAll(", "); |
| 419 | try s.dumpValue(w, item); | 420 | try s.dumpValue(w, item); |
| 420 | } | 421 | } |
src/core/Air.zig+6-21| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | insts: Inst.List.Slice, | 1 | insts: Inst.List.Slice, |
| 2 | extra: ExtraStore = .{}, | 2 | extra: ExtraStore, |
| 3 | 3 | ||
| 4 | pub const ExtraStore = dod.ExtraStore(.air, .@"const"); | 4 | pub const ExtraStore = dod.ExtraStore(.air, .@"const"); |
| 5 | pub const EncodedData = dod.EncodedData(Inst.Tag, u64); | 5 | pub const EncodedData = dod.EncodedData(Inst.Tag, u64); |
| ... | @@ -201,23 +201,8 @@ pub const Flags = packed struct { | ... | @@ -201,23 +201,8 @@ pub const Flags = packed struct { |
| 201 | }; | 201 | }; |
| 202 | }; | 202 | }; |
| 203 | 203 | ||
| 204 | pub const IndexList = struct { | 204 | pub const IndexList = ExtraStore.Slice(Air.Inst.Index); |
| 205 | start: u32, | 205 | pub const RefList = ExtraStore.Slice(Air.Inst.Ref); |
| 206 | len: u32, | ||
| 207 | |||
| 208 | pub fn slice(self: IndexList, air: *const Air) []const Inst.Index { | ||
| 209 | return @ptrCast(air.extra.list.items[self.start..][0..self.len]); | ||
| 210 | } | ||
| 211 | }; | ||
| 212 | |||
| 213 | pub const RefList = struct { | ||
| 214 | start: u32, | ||
| 215 | len: u32, | ||
| 216 | |||
| 217 | pub fn slice(self: RefList, air: *const Air) []const Inst.Ref { | ||
| 218 | return @ptrCast(air.extra.list.items[self.start..][0..self.len]); | ||
| 219 | } | ||
| 220 | }; | ||
| 221 | 206 | ||
| 222 | pub const Break = struct { | 207 | pub const Break = struct { |
| 223 | block: Inst.Index, | 208 | block: Inst.Index, |
| ... | @@ -383,7 +368,7 @@ pub fn typeOfIndex(air: *const Air, index: Inst.Index, ip: *const InternPool) In | ... | @@ -383,7 +368,7 @@ pub fn typeOfIndex(air: *const Air, index: Inst.Index, ip: *const InternPool) In |
| 383 | // TODO: taking the last instruction is likely wrong. | 368 | // TODO: taking the last instruction is likely wrong. |
| 384 | // The last instruction is going to be a .break and be of type .never | 369 | // The last instruction is going to be a .break and be of type .never |
| 385 | .block => { | 370 | .block => { |
| 386 | const items = air.instData(.block, index).slice(air); | 371 | const items = air.instData(.block, index).get(air); |
| 387 | assert(items.len > 0); // empty blocks should always be `Value.void` | 372 | assert(items.len > 0); // empty blocks should always be `Value.void` |
| 388 | return air.typeOfIndex(items[items.len - 1], ip); | 373 | return air.typeOfIndex(items[items.len - 1], ip); |
| 389 | }, | 374 | }, |
| ... | @@ -402,7 +387,7 @@ pub fn typeOfIndex(air: *const Air, index: Inst.Index, ip: *const InternPool) In | ... | @@ -402,7 +387,7 @@ pub fn typeOfIndex(air: *const Air, index: Inst.Index, ip: *const InternPool) In |
| 402 | const inst = air.instData(.field_struct, index); | 387 | const inst = air.instData(.field_struct, index); |
| 403 | const base_type = air.typeOfIndex(inst.base, ip) | 388 | const base_type = air.typeOfIndex(inst.base, ip) |
| 404 | .toStructType(ip) orelse unreachable; // field_struct demands struct type | 389 | .toStructType(ip) orelse unreachable; // field_struct demands struct type |
| 405 | return base_type.field_types[inst.field_index]; | 390 | return base_type.field_types.at(ip, inst.field_index); |
| 406 | }, | 391 | }, |
| 407 | 392 | ||
| 408 | // Array accesses use the array they are accessing into. | 393 | // Array accesses use the array they are accessing into. |
| ... | @@ -418,7 +403,7 @@ pub fn typeOfIndex(air: *const Air, index: Inst.Index, ip: *const InternPool) In | ... | @@ -418,7 +403,7 @@ pub fn typeOfIndex(air: *const Air, index: Inst.Index, ip: *const InternPool) In |
| 418 | const inst = air.instData(.field_tuple, index); | 403 | const inst = air.instData(.field_tuple, index); |
| 419 | const base_type = air.typeOfIndex(inst.base, ip) | 404 | const base_type = air.typeOfIndex(inst.base, ip) |
| 420 | .toTupleType(ip) orelse unreachable; // field_tuple demands tuple type | 405 | .toTupleType(ip) orelse unreachable; // field_tuple demands tuple type |
| 421 | return base_type.items[inst.field_index]; | 406 | return base_type.items.at(ip, inst.field_index); |
| 422 | }, | 407 | }, |
| 423 | }; | 408 | }; |
| 424 | } | 409 | } |
src/core/Hir.zig+1-1| ... | @@ -13,7 +13,7 @@ | ... | @@ -13,7 +13,7 @@ |
| 13 | 13 | ||
| 14 | insts: Inst.List.Slice, | 14 | insts: Inst.List.Slice, |
| 15 | string_bytes: []const u8, | 15 | string_bytes: []const u8, |
| 16 | extra: ExtraStore = .{}, | 16 | extra: ExtraStore, |
| 17 | report: Report, | 17 | report: Report, |
| 18 | 18 | ||
| 19 | pub const ExtraStore = dod.ExtraStore(.hir, .@"const"); | 19 | pub const ExtraStore = dod.ExtraStore(.hir, .@"const"); |
src/core/InternPool.zig+91-104| ... | @@ -21,9 +21,9 @@ | ... | @@ -21,9 +21,9 @@ |
| 21 | /// | 21 | /// |
| 22 | /// The preferred way to access these this data through `.get()` and the methods | 22 | /// The preferred way to access these this data through `.get()` and the methods |
| 23 | /// on `Value` and `Type`. | 23 | /// on `Value` and `Type`. |
| 24 | map: std.AutoArrayHashMapUnmanaged(void, void) = .{}, | 24 | map: std.AutoArrayHashMapUnmanaged(void, void) = .empty, |
| 25 | items: std.MultiArrayList(Item) = .{}, | 25 | items: std.MultiArrayList(Item) = .empty, |
| 26 | extra: ExtraStore = .{}, | 26 | extra: Extra = .empty, |
| 27 | 27 | ||
| 28 | /// In order to store references to strings in fewer bytes, we copy all | 28 | /// In order to store references to strings in fewer bytes, we copy all |
| 29 | /// string bytes into here. String bytes can be null. It is up to whoever | 29 | /// string bytes into here. String bytes can be null. It is up to whoever |
| ... | @@ -146,7 +146,7 @@ pub const Tag = enum(u8) { | ... | @@ -146,7 +146,7 @@ pub const Tag = enum(u8) { |
| 146 | .int32 => i32, | 146 | .int32 => i32, |
| 147 | .opaque_value => Value, | 147 | .opaque_value => Value, |
| 148 | 148 | ||
| 149 | else => ExtraIndex(tag.Payload()), | 149 | else => Extra.Index(tag.Payload()), |
| 150 | }; | 150 | }; |
| 151 | } | 151 | } |
| 152 | 152 | ||
| ... | @@ -270,18 +270,7 @@ pub const Value = enum(u32) { | ... | @@ -270,18 +270,7 @@ pub const Value = enum(u32) { |
| 270 | none = std.math.maxInt(u32), | 270 | none = std.math.maxInt(u32), |
| 271 | _, | 271 | _, |
| 272 | 272 | ||
| 273 | /// An array of `Value` existing within the `extra` array. | 273 | pub const Slice = Extra.Slice(Value); |
| 274 | /// This type exists to provide a struct with lifetime that is | ||
| 275 | /// not invalidated when items are added to the `InternPool`. | ||
| 276 | // TODO: Replace with ExtraStore.Slice(Value) | ||
| 277 | pub const Slice = struct { | ||
| 278 | start: u32, | ||
| 279 | len: u32, | ||
| 280 | |||
| 281 | pub fn get(slice: Slice, ip: *const InternPool) []const Value { | ||
| 282 | return @ptrCast(ip.extra.list.items[slice.start..][0..slice.len]); | ||
| 283 | } | ||
| 284 | }; | ||
| 285 | 274 | ||
| 286 | /// Used for a map of `Value` values to the index within a list of `Value` values. | 275 | /// Used for a map of `Value` values to the index within a list of `Value` values. |
| 287 | const Adapter = struct { | 276 | const Adapter = struct { |
| ... | @@ -316,6 +305,8 @@ pub const Value = enum(u32) { | ... | @@ -316,6 +305,8 @@ pub const Value = enum(u32) { |
| 316 | 305 | ||
| 317 | pub fn assertValid(value: Value, ip: *const InternPool) void { | 306 | pub fn assertValid(value: Value, ip: *const InternPool) void { |
| 318 | assert(@intFromEnum(value) < ip.items.len); | 307 | assert(@intFromEnum(value) < ip.items.len); |
| 308 | assert(value != .none); | ||
| 309 | assert(ip.items.items(.tag)[@intFromEnum(value)] != .removed); | ||
| 319 | } | 310 | } |
| 320 | 311 | ||
| 321 | pub fn dump(value: Value, ip: *const InternPool) std.fmt.Formatter(Value.formatValue) { | 312 | pub fn dump(value: Value, ip: *const InternPool) std.fmt.Formatter(Value.formatValue) { |
| ... | @@ -459,17 +450,7 @@ pub const Type = enum(u32) { | ... | @@ -459,17 +450,7 @@ pub const Type = enum(u32) { |
| 459 | tuple_type = @intFromEnum(InternPool.Tag.tuple_type), | 450 | tuple_type = @intFromEnum(InternPool.Tag.tuple_type), |
| 460 | }; | 451 | }; |
| 461 | 452 | ||
| 462 | /// An array of `Index` existing within the `extra` array. | 453 | pub const Slice = Extra.Slice(Type); |
| 463 | /// This type exists to provide a struct with lifetime that is | ||
| 464 | /// not invalidated when items are added to the `InternPool`. | ||
| 465 | pub const Slice = struct { | ||
| 466 | start: u32, | ||
| 467 | len: u32, | ||
| 468 | |||
| 469 | pub fn get(slice: Slice, ip: *const InternPool) []Type { | ||
| 470 | return @ptrCast(ip.extra.list.items[slice.start..][0..slice.len]); | ||
| 471 | } | ||
| 472 | }; | ||
| 473 | 454 | ||
| 474 | pub fn value(ty: Type) Value { | 455 | pub fn value(ty: Type) Value { |
| 475 | return @enumFromInt(@intFromEnum(ty)); | 456 | return @enumFromInt(@intFromEnum(ty)); |
| ... | @@ -526,7 +507,7 @@ pub const Type = enum(u32) { | ... | @@ -526,7 +507,7 @@ pub const Type = enum(u32) { |
| 526 | => true, | 507 | => true, |
| 527 | .tuple_type => { | 508 | .tuple_type => { |
| 528 | const tuple_type = ty.toTupleType(ip).?; | 509 | const tuple_type = ty.toTupleType(ip).?; |
| 529 | for (tuple_type.items) |item| { | 510 | for (tuple_type.items.get(ip)) |item| { |
| 530 | if (!item.hasPossibleRepresentation(ip)) { | 511 | if (!item.hasPossibleRepresentation(ip)) { |
| 531 | return false; | 512 | return false; |
| 532 | } | 513 | } |
| ... | @@ -599,7 +580,7 @@ pub const Type = enum(u32) { | ... | @@ -599,7 +580,7 @@ pub const Type = enum(u32) { |
| 599 | .function_type => { | 580 | .function_type => { |
| 600 | const function_type = ty.toUnresolvedFunctionPrototype(ip).?; | 581 | const function_type = ty.toUnresolvedFunctionPrototype(ip).?; |
| 601 | try writer.writeAll("fn("); | 582 | try writer.writeAll("fn("); |
| 602 | for (function_type.param_types, 0..) |param, i| { | 583 | for (function_type.param_types.get(ip), 0..) |param, i| { |
| 603 | if (i != 0) try writer.writeAll(", "); | 584 | if (i != 0) try writer.writeAll(", "); |
| 604 | try writer.print("{}", .{param.displayName(ip)}); | 585 | try writer.print("{}", .{param.displayName(ip)}); |
| 605 | } | 586 | } |
| ... | @@ -619,7 +600,7 @@ pub const Type = enum(u32) { | ... | @@ -619,7 +600,7 @@ pub const Type = enum(u32) { |
| 619 | }, | 600 | }, |
| 620 | .tuple_type => { | 601 | .tuple_type => { |
| 621 | try writer.writeAll("("); | 602 | try writer.writeAll("("); |
| 622 | for (ty.toTupleType(ip).?.items, 0..) |item, i| { | 603 | for (ty.toTupleType(ip).?.items.get(ip), 0..) |item, i| { |
| 623 | if (i != 0) try writer.writeAll(", "); | 604 | if (i != 0) try writer.writeAll(", "); |
| 624 | try writer.print("{}", .{item.displayName(ip)}); | 605 | try writer.print("{}", .{item.displayName(ip)}); |
| 625 | } | 606 | } |
| ... | @@ -651,9 +632,8 @@ pub const Item = struct { | ... | @@ -651,9 +632,8 @@ pub const Item = struct { |
| 651 | } | 632 | } |
| 652 | }; | 633 | }; |
| 653 | 634 | ||
| 654 | pub const ExtraStore = dod.ExtraStore(.intern_pool, .@"var"); | 635 | pub const Extra = dod.ExtraStore(.intern_pool, .@"var"); |
| 655 | pub const EncodedData = dod.EncodedData(Tag, u32); | 636 | pub const EncodedData = dod.EncodedData(Tag, u32); |
| 656 | pub const ExtraIndex = ExtraStore.Index; | ||
| 657 | 637 | ||
| 658 | /// How many items in the InternPool are statically known. | 638 | /// How many items in the InternPool are statically known. |
| 659 | /// This is specified with an integer literal and a corresponding comptime | 639 | /// This is specified with an integer literal and a corresponding comptime |
| ... | @@ -674,9 +654,9 @@ pub const static_keys = [_]Key{ | ... | @@ -674,9 +654,9 @@ pub const static_keys = [_]Key{ |
| 674 | SimpleType.never.key(), | 654 | SimpleType.never.key(), |
| 675 | SimpleType.type.key(), | 655 | SimpleType.type.key(), |
| 676 | SimpleType.numeric_literal.key(), | 656 | SimpleType.numeric_literal.key(), |
| 677 | .{ .array_type = .{ .item_type = Type.numeric_literal } }, | 657 | .{ .array_type = .{ .item_type = .numeric_literal } }, |
| 678 | .{ .array_type = .{ .item_type = Type.never } }, | 658 | .{ .array_type = .{ .item_type = .never } }, |
| 679 | .{ .tuple_type = .{ .items = &.{} } }, | 659 | .{ .tuple_type = .{ .items = .empty } }, |
| 680 | 660 | ||
| 681 | SimpleValue.void.key(), | 661 | SimpleValue.void.key(), |
| 682 | SimpleValue.true.key(), | 662 | SimpleValue.true.key(), |
| ... | @@ -685,13 +665,13 @@ pub const static_keys = [_]Key{ | ... | @@ -685,13 +665,13 @@ pub const static_keys = [_]Key{ |
| 685 | .{ .float = 0.0 }, | 665 | .{ .float = 0.0 }, |
| 686 | .{ .float = Float.pure_nan.decode() }, | 666 | .{ .float = Float.pure_nan.decode() }, |
| 687 | .{ .array_value = .{ | 667 | .{ .array_value = .{ |
| 688 | .type = Type.never_array, | 668 | .type = .never_array, |
| 689 | .items = &.{}, | 669 | .items = .empty, |
| 690 | } }, | 670 | } }, |
| 691 | .{ .string = "" }, | 671 | .{ .string = "" }, |
| 692 | .{ .tuple_value = .{ | 672 | .{ .tuple_value = .{ |
| 693 | .type = .empty_tuple, | 673 | .type = .empty_tuple, |
| 694 | .items = &.{}, | 674 | .items = .empty, |
| 695 | } }, | 675 | } }, |
| 696 | }; | 676 | }; |
| 697 | 677 | ||
| ... | @@ -814,14 +794,7 @@ pub const NullTerminatedString = enum(u32) { | ... | @@ -814,14 +794,7 @@ pub const NullTerminatedString = enum(u32) { |
| 814 | return .{ .data = .{ .string = self, .ip = ip } }; | 794 | return .{ .data = .{ .string = self, .ip = ip } }; |
| 815 | } | 795 | } |
| 816 | 796 | ||
| 817 | pub const Slice = struct { | 797 | pub const Slice = Extra.Slice(NullTerminatedString); |
| 818 | start: u32, | ||
| 819 | len: u32, | ||
| 820 | |||
| 821 | pub fn get(slice: Slice, ip: *const InternPool) []NullTerminatedString { | ||
| 822 | return @ptrCast(ip.extra.list.items[slice.start..][0..slice.len]); | ||
| 823 | } | ||
| 824 | }; | ||
| 825 | }; | 798 | }; |
| 826 | 799 | ||
| 827 | pub const TrackedInst = extern struct { | 800 | pub const TrackedInst = extern struct { |
| ... | @@ -975,66 +948,74 @@ pub const Key = union(enum) { | ... | @@ -975,66 +948,74 @@ pub const Key = union(enum) { |
| 975 | }; | 948 | }; |
| 976 | 949 | ||
| 977 | pub const FunctionType = struct { | 950 | pub const FunctionType = struct { |
| 978 | param_types: []Type, | 951 | param_types: Type.Slice, |
| 979 | /// If a return type is missing, it is inferred and not resolved yet. | 952 | /// If a return type is missing, it is inferred and not resolved yet. |
| 980 | /// When analysis figures out a return type, a new `FunctionType` with | 953 | /// When analysis figures out a return type, a new `FunctionType` with |
| 981 | /// the resolved return type. | 954 | /// the resolved return type. |
| 982 | return_type: ?Type, | 955 | return_type: ?Type, |
| 983 | 956 | ||
| 984 | pub const Resolved = struct { | 957 | pub const Resolved = struct { |
| 985 | param_types: []Type, | 958 | param_types: Type.Slice, |
| 986 | return_type: Type, | 959 | return_type: Type, |
| 987 | }; | 960 | }; |
| 988 | 961 | ||
| 989 | pub fn hash(self: FunctionType, hasher: *Hash) void { | 962 | pub fn hash(self: FunctionType, ip: *const InternPool, hasher: *Hash) void { |
| 990 | const t = tracer.trace(@src()); | 963 | const t = tracer.trace(@src()); |
| 991 | defer t.end(); | 964 | defer t.end(); |
| 992 | 965 | ||
| 993 | for (self.param_types) |param_type| { | 966 | for (self.param_types.get(ip)) |param_type| { |
| 994 | std.hash.autoHash(hasher, param_type); | 967 | std.hash.autoHash(hasher, param_type); |
| 995 | } | 968 | } |
| 996 | std.hash.autoHash(hasher, self.return_type); | 969 | std.hash.autoHash(hasher, self.return_type); |
| 997 | } | 970 | } |
| 998 | 971 | ||
| 999 | pub fn eql(a: FunctionType, b: FunctionType) bool { | 972 | pub fn eql(a: FunctionType, b: FunctionType, ip: *const InternPool) bool { |
| 1000 | return std.mem.eql(Type, a.param_types, b.param_types) and | 973 | return std.mem.eql(Type, a.param_types.get(ip), b.param_types.get(ip)) and |
| 1001 | a.return_type == b.return_type; | 974 | a.return_type == b.return_type; |
| 1002 | } | 975 | } |
| 1003 | }; | 976 | }; |
| 1004 | 977 | ||
| 1005 | pub const StructType = struct { | 978 | pub const StructType = struct { |
| 1006 | field_keys: []NullTerminatedString, | 979 | field_keys: NullTerminatedString.Slice, |
| 1007 | field_types: []const Type, | 980 | field_types: Type.Slice, |
| 1008 | 981 | ||
| 1009 | pub fn hash(self: StructType, hasher: *Hash) void { | 982 | /// TODO: store where the struct is declared to make this a nomial type |
| 1010 | // TODO: remove this function. structural typing is not used | 983 | pub fn hash(self: StructType, ip: *const InternPool, hasher: *Hash) void { |
| 1011 | // this should be hashing it's location / decl, exactly like `Func` | 984 | for (self.field_keys.get(ip)) |value| { |
| 1012 | std.hash.autoHashStrat(hasher, self, .DeepRecursive); | 985 | std.hash.autoHash(hasher, value); |
| 986 | } | ||
| 987 | for (self.field_types.get(ip)) |value| { | ||
| 988 | std.hash.autoHash(hasher, value); | ||
| 989 | } | ||
| 1013 | } | 990 | } |
| 1014 | }; | 991 | }; |
| 1015 | 992 | ||
| 1016 | pub const StructValue = struct { | 993 | pub const StructValue = struct { |
| 1017 | ty: Type, | 994 | ty: Type, |
| 1018 | field_values: []const Value, | 995 | field_values: Value.Slice, |
| 1019 | 996 | ||
| 1020 | pub fn hash(self: StructValue, hasher: *Hash) void { | 997 | pub fn hash(self: StructValue, ip: *const InternPool, hasher: *Hash) void { |
| 1021 | std.hash.autoHash(hasher, self.ty); | 998 | std.hash.autoHash(hasher, self.ty); |
| 1022 | std.hash.autoHashStrat(hasher, self.field_values, .Deep); | 999 | for (self.field_values.get(ip)) |value| { |
| 1000 | std.hash.autoHash(hasher, value); | ||
| 1001 | } | ||
| 1023 | } | 1002 | } |
| 1024 | }; | 1003 | }; |
| 1025 | 1004 | ||
| 1026 | pub const ArrayType = struct { | 1005 | pub const ArrayType = struct { |
| 1027 | item_type: Type, | 1006 | item_type: Type, |
| 1028 | 1007 | ||
| 1029 | pub fn hash(self: ArrayType, hasher: *Hash) void { | 1008 | pub fn hash(self: ArrayType, ip: *const InternPool, hasher: *Hash) void { |
| 1009 | _ = ip; | ||
| 1030 | std.hash.autoHash(hasher, self.item_type); | 1010 | std.hash.autoHash(hasher, self.item_type); |
| 1031 | } | 1011 | } |
| 1032 | }; | 1012 | }; |
| 1033 | 1013 | ||
| 1034 | pub const TupleType = struct { | 1014 | pub const TupleType = struct { |
| 1035 | items: []const Type, | 1015 | items: Type.Slice, |
| 1036 | 1016 | ||
| 1037 | pub fn hash(self: TupleType, hasher: *Hash) void { | 1017 | pub fn hash(self: TupleType, ip: *const InternPool, hasher: *Hash) void { |
| 1018 | _ = ip; | ||
| 1038 | std.hash.autoHashStrat(hasher, self.items, .Deep); | 1019 | std.hash.autoHashStrat(hasher, self.items, .Deep); |
| 1039 | } | 1020 | } |
| 1040 | }; | 1021 | }; |
| ... | @@ -1042,30 +1023,31 @@ pub const Key = union(enum) { | ... | @@ -1042,30 +1023,31 @@ pub const Key = union(enum) { |
| 1042 | pub const ExternalValue = struct { | 1023 | pub const ExternalValue = struct { |
| 1043 | /// A list of strings to generate the property access | 1024 | /// A list of strings to generate the property access |
| 1044 | /// so `console.log` would be .{ "console", "log" } | 1025 | /// so `console.log` would be .{ "console", "log" } |
| 1045 | key: []const NullTerminatedString, | 1026 | key: NullTerminatedString.Slice, |
| 1046 | 1027 | ||
| 1047 | pub fn hash(self: ExternalValue, hasher: *Hash) void { | 1028 | pub fn hash(self: ExternalValue, ip: *const InternPool, hasher: *Hash) void { |
| 1048 | std.hash.autoHashStrat(hasher, self.key, .Shallow); | 1029 | std.hash.autoHashStrat(hasher, self.key.get(ip), .Shallow); |
| 1049 | } | 1030 | } |
| 1050 | }; | 1031 | }; |
| 1051 | 1032 | ||
| 1052 | pub const ArrayValue = struct { | 1033 | pub const ArrayValue = struct { |
| 1053 | /// This is the array type, not the item type | 1034 | /// This is the array type, not the item type |
| 1054 | type: Type, | 1035 | type: Type, |
| 1055 | items: []const Value, | 1036 | items: Value.Slice, |
| 1056 | 1037 | ||
| 1057 | pub fn hash(self: ArrayValue, hasher: *Hash) void { | 1038 | pub fn hash(self: ArrayValue, ip: *const InternPool, hasher: *Hash) void { |
| 1058 | std.hash.autoHash(hasher, self.type); | 1039 | std.hash.autoHash(hasher, self.type); |
| 1059 | std.hash.autoHashStrat(hasher, self.items, .Deep); | 1040 | std.hash.autoHashStrat(hasher, self.items.get(ip), .Deep); |
| 1060 | } | 1041 | } |
| 1061 | }; | 1042 | }; |
| 1062 | 1043 | ||
| 1063 | pub const TupleValue = struct { | 1044 | pub const TupleValue = struct { |
| 1064 | /// This is the tuple type, not the item type | 1045 | /// This is the tuple type, not the item type |
| 1065 | type: Type, | 1046 | type: Type, |
| 1066 | items: []const Value, | 1047 | items: Value.Slice, |
| 1067 | 1048 | ||
| 1068 | pub fn hash(self: TupleValue, hasher: *Hash) void { | 1049 | pub fn hash(self: TupleValue, ip: *const InternPool, hasher: *Hash) void { |
| 1050 | _ = ip; | ||
| 1069 | std.hash.autoHash(hasher, self.type); | 1051 | std.hash.autoHash(hasher, self.type); |
| 1070 | std.hash.autoHashStrat(hasher, self.items, .Deep); | 1052 | std.hash.autoHashStrat(hasher, self.items, .Deep); |
| 1071 | } | 1053 | } |
| ... | @@ -1075,9 +1057,10 @@ pub const Key = union(enum) { | ... | @@ -1075,9 +1057,10 @@ pub const Key = union(enum) { |
| 1075 | ty: Type, | 1057 | ty: Type, |
| 1076 | owner_decl: DeclIndex, | 1058 | owner_decl: DeclIndex, |
| 1077 | teg_body_inst: TrackedInst.Index, | 1059 | teg_body_inst: TrackedInst.Index, |
| 1078 | analysis: ExtraIndex(AnalysisState), | 1060 | analysis: Extra.Index(AnalysisState), |
| 1079 | 1061 | ||
| 1080 | pub fn hash(self: Func, hasher: *Hash) void { | 1062 | pub fn hash(self: Func, ip: *const InternPool, hasher: *Hash) void { |
| 1063 | _ = ip; | ||
| 1081 | std.hash.autoHash(hasher, self.ty); | 1064 | std.hash.autoHash(hasher, self.ty); |
| 1082 | std.hash.autoHash(hasher, self.owner_decl); | 1065 | std.hash.autoHash(hasher, self.owner_decl); |
| 1083 | std.hash.autoHash(hasher, self.teg_body_inst); | 1066 | std.hash.autoHash(hasher, self.teg_body_inst); |
| ... | @@ -1095,7 +1078,6 @@ pub const Key = union(enum) { | ... | @@ -1095,7 +1078,6 @@ pub const Key = union(enum) { |
| 1095 | } | 1078 | } |
| 1096 | 1079 | ||
| 1097 | pub fn hash64(key: Key, ip: *const InternPool) u64 { | 1080 | pub fn hash64(key: Key, ip: *const InternPool) u64 { |
| 1098 | _ = ip; // autofix | ||
| 1099 | const t = tracer.trace(@src()); | 1081 | const t = tracer.trace(@src()); |
| 1100 | defer t.end(); | 1082 | defer t.end(); |
| 1101 | 1083 | ||
| ... | @@ -1114,8 +1096,8 @@ pub const Key = union(enum) { | ... | @@ -1114,8 +1096,8 @@ pub const Key = union(enum) { |
| 1114 | .float, .comptime_float => |x| Hash.hash(seed, asBytes(&Float.assertPure(x))), | 1096 | .float, .comptime_float => |x| Hash.hash(seed, asBytes(&Float.assertPure(x))), |
| 1115 | inline .function_type, | 1097 | inline .function_type, |
| 1116 | .func, | 1098 | .func, |
| 1117 | .struct_type, | ||
| 1118 | .struct_value, | 1099 | .struct_value, |
| 1100 | .struct_type, | ||
| 1119 | .array_value, | 1101 | .array_value, |
| 1120 | .array_type, | 1102 | .array_type, |
| 1121 | .external_value, | 1103 | .external_value, |
| ... | @@ -1123,14 +1105,13 @@ pub const Key = union(enum) { | ... | @@ -1123,14 +1105,13 @@ pub const Key = union(enum) { |
| 1123 | .tuple_value, | 1105 | .tuple_value, |
| 1124 | => |x| { | 1106 | => |x| { |
| 1125 | var hasher = Hash.init(seed); | 1107 | var hasher = Hash.init(seed); |
| 1126 | x.hash(&hasher); | 1108 | x.hash(ip, &hasher); |
| 1127 | return hasher.final(); | 1109 | return hasher.final(); |
| 1128 | }, | 1110 | }, |
| 1129 | }; | 1111 | }; |
| 1130 | } | 1112 | } |
| 1131 | 1113 | ||
| 1132 | pub fn eql(a: Key, b: Key, ip: *const InternPool) bool { | 1114 | pub fn eql(a: Key, b: Key, ip: *const InternPool) bool { |
| 1133 | _ = ip; // autofix | ||
| 1134 | const t = tracer.trace(@src()); | 1115 | const t = tracer.trace(@src()); |
| 1135 | defer t.end(); | 1116 | defer t.end(); |
| 1136 | 1117 | ||
| ... | @@ -1148,7 +1129,7 @@ pub const Key = union(enum) { | ... | @@ -1148,7 +1129,7 @@ pub const Key = union(enum) { |
| 1148 | => |x| std.mem.eql(u8, x, b.string), | 1129 | => |x| std.mem.eql(u8, x, b.string), |
| 1149 | .float => |x| Float.assertPure(x) == Float.assertPure(b.float), | 1130 | .float => |x| Float.assertPure(x) == Float.assertPure(b.float), |
| 1150 | .comptime_float => |x| Float.assertPure(x) == Float.assertPure(b.comptime_float), | 1131 | .comptime_float => |x| Float.assertPure(x) == Float.assertPure(b.comptime_float), |
| 1151 | .function_type => |x| x.eql(b.function_type), | 1132 | .function_type => |x| x.eql(b.function_type, ip), |
| 1152 | .func => |a_info| { | 1133 | .func => |a_info| { |
| 1153 | const b_info = b.func; | 1134 | const b_info = b.func; |
| 1154 | if (a_info.owner_decl != b_info.owner_decl) | 1135 | if (a_info.owner_decl != b_info.owner_decl) |
| ... | @@ -1165,7 +1146,7 @@ pub const Key = union(enum) { | ... | @@ -1165,7 +1146,7 @@ pub const Key = union(enum) { |
| 1165 | .struct_value => |a_info| { | 1146 | .struct_value => |a_info| { |
| 1166 | const b_info = b.struct_value; | 1147 | const b_info = b.struct_value; |
| 1167 | return a_info.ty == b_info.ty and | 1148 | return a_info.ty == b_info.ty and |
| 1168 | std.mem.eql(Value, a_info.field_values, b_info.field_values); | 1149 | std.mem.eql(Value, a_info.field_values.get(ip), b_info.field_values.get(ip)); |
| 1169 | }, | 1150 | }, |
| 1170 | .array_type => |a_info| { | 1151 | .array_type => |a_info| { |
| 1171 | return a_info.item_type == b.array_type.item_type; | 1152 | return a_info.item_type == b.array_type.item_type; |
| ... | @@ -1173,20 +1154,21 @@ pub const Key = union(enum) { | ... | @@ -1173,20 +1154,21 @@ pub const Key = union(enum) { |
| 1173 | .array_value => |a_info| { | 1154 | .array_value => |a_info| { |
| 1174 | const b_info = b.array_value; | 1155 | const b_info = b.array_value; |
| 1175 | return a_info.type == b_info.type and | 1156 | return a_info.type == b_info.type and |
| 1176 | std.mem.eql(Value, a_info.items, b_info.items); | 1157 | std.mem.eql(Value, a_info.items.get(ip), b_info.items.get(ip)); |
| 1177 | }, | 1158 | }, |
| 1178 | .external_value => |a_info| { | 1159 | .external_value => |a_info| { |
| 1179 | const b_info = b.external_value; | 1160 | const b_info = b.external_value; |
| 1180 | return std.mem.eql(NullTerminatedString, a_info.key, b_info.key); | 1161 | return std.mem.eql(NullTerminatedString, a_info.key.get(ip), b_info.key.get(ip)); |
| 1181 | }, | 1162 | }, |
| 1182 | .tuple_type => |a_info| { | 1163 | .tuple_type => |a_info| { |
| 1183 | const b_info = b.tuple_type; | 1164 | const b_info = b.tuple_type; |
| 1184 | return a_info.items.len == b_info.items.len and std.mem.eql(Type, a_info.items, b_info.items); | 1165 | return a_info.items.len == b_info.items.len and |
| 1166 | std.mem.eql(Type, a_info.items.get(ip), b_info.items.get(ip)); | ||
| 1185 | }, | 1167 | }, |
| 1186 | .tuple_value => |a_info| { | 1168 | .tuple_value => |a_info| { |
| 1187 | const b_info = b.tuple_value; | 1169 | const b_info = b.tuple_value; |
| 1188 | return a_info.type == b_info.type and | 1170 | return a_info.type == b_info.type and |
| 1189 | std.mem.eql(Value, a_info.items, b_info.items); | 1171 | std.mem.eql(Value, a_info.items.get(ip), b_info.items.get(ip)); |
| 1190 | }, | 1172 | }, |
| 1191 | }; | 1173 | }; |
| 1192 | } | 1174 | } |
| ... | @@ -1438,8 +1420,8 @@ pub fn valueToKey(ip: *const InternPool, index: Value) Key { | ... | @@ -1438,8 +1420,8 @@ pub fn valueToKey(ip: *const InternPool, index: Value) Key { |
| 1438 | data.decode(.struct_type, item.tag).getTrail(ip); | 1420 | data.decode(.struct_type, item.tag).getTrail(ip); |
| 1439 | 1421 | ||
| 1440 | return .{ .struct_type = .{ | 1422 | return .{ .struct_type = .{ |
| 1441 | .field_keys = trail.readNullTerminatedStringSlice(payload.fields_len).get(ip), | 1423 | .field_keys = trail.readNullTerminatedStringSlice(payload.fields_len), |
| 1442 | .field_types = trail.readTypeSlice(payload.fields_len).get(ip), | 1424 | .field_types = trail.readTypeSlice(payload.fields_len), |
| 1443 | } }; | 1425 | } }; |
| 1444 | }, | 1426 | }, |
| 1445 | .struct_value => { | 1427 | .struct_value => { |
| ... | @@ -1449,8 +1431,10 @@ pub fn valueToKey(ip: *const InternPool, index: Value) Key { | ... | @@ -1449,8 +1431,10 @@ pub fn valueToKey(ip: *const InternPool, index: Value) Key { |
| 1449 | return .{ .struct_value = .{ | 1431 | return .{ .struct_value = .{ |
| 1450 | .ty = payload.ty, | 1432 | .ty = payload.ty, |
| 1451 | .field_values = trail.readValueSlice( | 1433 | .field_values = trail.readValueSlice( |
| 1452 | payload.ty.value().valueData(ip, .struct_type).get(ip).fields_len, | 1434 | payload.ty.value() |
| 1453 | ).get(ip), | 1435 | .valueData(ip, .struct_type) |
| 1436 | .get(ip).fields_len, | ||
| 1437 | ), | ||
| 1454 | } }; | 1438 | } }; |
| 1455 | }, | 1439 | }, |
| 1456 | .array_type => { | 1440 | .array_type => { |
| ... | @@ -1463,31 +1447,34 @@ pub fn valueToKey(ip: *const InternPool, index: Value) Key { | ... | @@ -1463,31 +1447,34 @@ pub fn valueToKey(ip: *const InternPool, index: Value) Key { |
| 1463 | const payload: Tag.ArrayValue, var trail = data.decode(.array_value, item.tag).getTrail(ip); | 1447 | const payload: Tag.ArrayValue, var trail = data.decode(.array_value, item.tag).getTrail(ip); |
| 1464 | return .{ .array_value = .{ | 1448 | return .{ .array_value = .{ |
| 1465 | .type = payload.type, | 1449 | .type = payload.type, |
| 1466 | .items = trail.readValueSlice(payload.items_len).get(ip), | 1450 | .items = trail.readValueSlice(payload.items_len), |
| 1467 | } }; | 1451 | } }; |
| 1468 | }, | 1452 | }, |
| 1469 | .external_value => { | 1453 | .external_value => { |
| 1470 | const payload: Tag.ExternalValue, var trail = data.decode(.external_value, item.tag).getTrail(ip); | 1454 | const payload: Tag.ExternalValue, var trail = data.decode(.external_value, item.tag).getTrail(ip); |
| 1471 | return .{ .external_value = .{ | 1455 | return .{ .external_value = .{ |
| 1472 | .key = trail.readNullTerminatedStringSlice(payload.key_count).get(ip), | 1456 | .key = trail.readNullTerminatedStringSlice(payload.key_count), |
| 1473 | } }; | 1457 | } }; |
| 1474 | }, | 1458 | }, |
| 1475 | .tuple_type => { | 1459 | .tuple_type => { |
| 1476 | const payload: Tag.TupleType, var trail = data.decode(.tuple_type, item.tag).getTrail(ip); | 1460 | const payload: Tag.TupleType, var trail = data.decode(.tuple_type, item.tag).getTrail(ip); |
| 1477 | return .{ .tuple_type = .{ | 1461 | return .{ .tuple_type = .{ |
| 1478 | .items = trail.readTypeSlice(payload.items_len).get(ip), | 1462 | .items = trail.readTypeSlice(payload.items_len), |
| 1479 | } }; | 1463 | } }; |
| 1480 | }, | 1464 | }, |
| 1481 | .tuple_value => { | 1465 | .tuple_value => { |
| 1482 | const payload: Tag.TupleValue, var trail = data.decode(.tuple_value, item.tag).getTrail(ip); | 1466 | const payload: Tag.TupleValue, var trail = data.decode(.tuple_value, item.tag).getTrail(ip); |
| 1483 | return .{ .tuple_value = .{ | 1467 | return .{ .tuple_value = .{ |
| 1484 | .type = payload.type, | 1468 | .type = payload.type, |
| 1485 | .items = trail.readValueSlice(payload.items_len).get(ip), | 1469 | .items = trail.readValueSlice(payload.items_len), |
| 1486 | } }; | 1470 | } }; |
| 1487 | }, | 1471 | }, |
| 1488 | }; | 1472 | }; |
| 1489 | } | 1473 | } |
| 1490 | 1474 | ||
| 1475 | // TODO: this function currently has a soft leak as `Key` requires slices into | ||
| 1476 | // InternPool, so querying for a something with a slice (function_type) will | ||
| 1477 | // always append it to `.extra` even if it becomes unused. | ||
| 1491 | pub fn get(ip: *InternPool, gpa: Allocator, key: Key) !Value { | 1478 | pub fn get(ip: *InternPool, gpa: Allocator, key: Key) !Value { |
| 1492 | const t = tracer.traceFmt(@src(), "{s}", .{@tagName(key)}); | 1479 | const t = tracer.traceFmt(@src(), "{s}", .{@tagName(key)}); |
| 1493 | defer t.end(); | 1480 | defer t.end(); |
| ... | @@ -1536,25 +1523,25 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) !Value { | ... | @@ -1536,25 +1523,25 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) !Value { |
| 1536 | break :brk Item.encode(.func, extra); | 1523 | break :brk Item.encode(.func, extra); |
| 1537 | }, | 1524 | }, |
| 1538 | .function_type => |f| brk: { | 1525 | .function_type => |f| brk: { |
| 1539 | for (f.param_types) |ty| ty.assertValid(ip); | 1526 | for (f.param_types.get(ip)) |ty| ty.assertValid(ip); |
| 1540 | 1527 | ||
| 1541 | const extra, var trail = try ip.extra.appendTrailing(gpa, Tag.FunctionType, .{ | 1528 | const extra, var trail = try ip.extra.appendTrailing(gpa, Tag.FunctionType, .{ |
| 1542 | .params_len = @intCast(f.param_types.len), | 1529 | .params_len = @intCast(f.param_types.len), |
| 1543 | .return_type = .init(f.return_type), | 1530 | .return_type = .init(f.return_type), |
| 1544 | }, f.param_types.len); | 1531 | }, f.param_types.len); |
| 1545 | defer trail.end(); | 1532 | defer trail.end(); |
| 1546 | trail.writeSlice(f.param_types); | 1533 | trail.writeSlice(f.param_types.get(ip)); |
| 1547 | break :brk Item.encode(.function_type, extra); | 1534 | break :brk Item.encode(.function_type, extra); |
| 1548 | }, | 1535 | }, |
| 1549 | .struct_type => |s| brk: { | 1536 | .struct_type => |s| brk: { |
| 1550 | for (s.field_types) |ty| ty.assertValid(ip); | 1537 | for (s.field_types.get(ip)) |ty| ty.assertValid(ip); |
| 1551 | 1538 | ||
| 1552 | assert(s.field_keys.len == s.field_types.len); | 1539 | assert(s.field_keys.len == s.field_types.len); |
| 1553 | const extra, var trail = try ip.extra.appendTrailing(gpa, Tag.StructType, .{ | 1540 | const extra, var trail = try ip.extra.appendTrailing(gpa, Tag.StructType, .{ |
| 1554 | .fields_len = @intCast(s.field_keys.len), | 1541 | .fields_len = @intCast(s.field_keys.len), |
| 1555 | }, s.field_keys.len * 2); | 1542 | }, s.field_keys.len * 2); |
| 1556 | trail.writeSlice(s.field_keys); | 1543 | trail.writeSlice(s.field_keys.get(ip)); |
| 1557 | trail.writeSlice(s.field_types); | 1544 | trail.writeSlice(s.field_types.get(ip)); |
| 1558 | 1545 | ||
| 1559 | break :brk Item.encode(.struct_type, extra); | 1546 | break :brk Item.encode(.struct_type, extra); |
| 1560 | }, | 1547 | }, |
| ... | @@ -1563,7 +1550,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) !Value { | ... | @@ -1563,7 +1550,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) !Value { |
| 1563 | const extra, var trail = try ip.extra.appendTrailing(gpa, Tag.StructValue, .{ | 1550 | const extra, var trail = try ip.extra.appendTrailing(gpa, Tag.StructValue, .{ |
| 1564 | .ty = s.ty, | 1551 | .ty = s.ty, |
| 1565 | }, s.field_values.len); | 1552 | }, s.field_values.len); |
| 1566 | trail.writeSlice(s.field_values); | 1553 | trail.writeSlice(s.field_values.get(ip)); |
| 1567 | break :brk Item.encode(.struct_value, extra); | 1554 | break :brk Item.encode(.struct_value, extra); |
| 1568 | }, | 1555 | }, |
| 1569 | .array_type => |s| brk: { | 1556 | .array_type => |s| brk: { |
| ... | @@ -1576,21 +1563,21 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) !Value { | ... | @@ -1576,21 +1563,21 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) !Value { |
| 1576 | .type = s.type, | 1563 | .type = s.type, |
| 1577 | .items_len = @intCast(s.items.len), | 1564 | .items_len = @intCast(s.items.len), |
| 1578 | }, s.items.len); | 1565 | }, s.items.len); |
| 1579 | trail.writeSlice(s.items); | 1566 | trail.writeSlice(s.items.get(ip)); |
| 1580 | break :brk Item.encode(.array_value, extra); | 1567 | break :brk Item.encode(.array_value, extra); |
| 1581 | }, | 1568 | }, |
| 1582 | .external_value => |s| brk: { | 1569 | .external_value => |s| brk: { |
| 1583 | const extra, var trail = try ip.extra.appendTrailing(gpa, Tag.ExternalValue, .{ | 1570 | const extra, var trail = try ip.extra.appendTrailing(gpa, Tag.ExternalValue, .{ |
| 1584 | .key_count = @intCast(s.key.len), | 1571 | .key_count = @intCast(s.key.len), |
| 1585 | }, s.key.len); | 1572 | }, s.key.len); |
| 1586 | trail.writeSlice(s.key); | 1573 | trail.writeSlice(s.key.get(ip)); |
| 1587 | break :brk Item.encode(.external_value, extra); | 1574 | break :brk Item.encode(.external_value, extra); |
| 1588 | }, | 1575 | }, |
| 1589 | .tuple_type => |s| brk: { | 1576 | .tuple_type => |s| brk: { |
| 1590 | const extra, var trail = try ip.extra.appendTrailing(gpa, Tag.TupleType, .{ | 1577 | const extra, var trail = try ip.extra.appendTrailing(gpa, Tag.TupleType, .{ |
| 1591 | .items_len = @intCast(s.items.len), | 1578 | .items_len = @intCast(s.items.len), |
| 1592 | }, s.items.len); | 1579 | }, s.items.len); |
| 1593 | trail.writeSlice(s.items); | 1580 | trail.writeSlice(s.items.get(ip)); |
| 1594 | break :brk Item.encode(.tuple_type, extra); | 1581 | break :brk Item.encode(.tuple_type, extra); |
| 1595 | }, | 1582 | }, |
| 1596 | .tuple_value => |s| brk: { | 1583 | .tuple_value => |s| brk: { |
| ... | @@ -1598,7 +1585,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) !Value { | ... | @@ -1598,7 +1585,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) !Value { |
| 1598 | .type = s.type, | 1585 | .type = s.type, |
| 1599 | .items_len = @intCast(s.items.len), | 1586 | .items_len = @intCast(s.items.len), |
| 1600 | }, s.items.len); | 1587 | }, s.items.len); |
| 1601 | trail.writeSlice(s.items); | 1588 | trail.writeSlice(s.items.get(ip)); |
| 1602 | break :brk Item.encode(.tuple_value, extra); | 1589 | break :brk Item.encode(.tuple_value, extra); |
| 1603 | }, | 1590 | }, |
| 1604 | }; | 1591 | }; |
| ... | @@ -1613,13 +1600,13 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) !Value { | ... | @@ -1613,13 +1600,13 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) !Value { |
| 1613 | 1600 | ||
| 1614 | fn extraTypeFunction( | 1601 | fn extraTypeFunction( |
| 1615 | ip: *const InternPool, | 1602 | ip: *const InternPool, |
| 1616 | extra_index: ExtraIndex(Tag.FunctionType), | 1603 | extra_index: Extra.Index(Tag.FunctionType), |
| 1617 | ) Key.FunctionType { | 1604 | ) Key.FunctionType { |
| 1618 | const function_type, var trail = extra_index.getTrail(ip); | 1605 | const function_type, var trail = extra_index.getTrail(ip); |
| 1619 | const param_types = trail.readTypeSlice(function_type.params_len); | 1606 | const param_types = trail.readTypeSlice(function_type.params_len); |
| 1620 | const result: Key.FunctionType = .{ | 1607 | const result: Key.FunctionType = .{ |
| 1621 | .return_type = function_type.return_type.unwrap(), | 1608 | .return_type = function_type.return_type.unwrap(), |
| 1622 | .param_types = param_types.get(ip), | 1609 | .param_types = param_types, |
| 1623 | }; | 1610 | }; |
| 1624 | return result; | 1611 | return result; |
| 1625 | } | 1612 | } |
src/core/Report.zig+6-7| ... | @@ -111,8 +111,7 @@ pub const Err = union(enum) { | ... | @@ -111,8 +111,7 @@ pub const Err = union(enum) { |
| 111 | }, | 111 | }, |
| 112 | no_main_func: struct { | 112 | no_main_func: struct { |
| 113 | fn build(_: @This(), ctx: *MsgContext) !void { | 113 | fn build(_: @This(), ctx: *MsgContext) !void { |
| 114 | // TODO: variant that includes file, but no location | 114 | try ctx.msg(.{ .codepoint_eol = 0 }, "missing top-level function \"main\"", .{}); |
| 115 | try ctx.msgToken(0, "missing top-level function \"main\"", .{}); | ||
| 116 | } | 115 | } |
| 117 | }, | 116 | }, |
| 118 | unknown_identifier: struct { | 117 | unknown_identifier: struct { |
| ... | @@ -455,7 +454,8 @@ pub const Err = union(enum) { | ... | @@ -455,7 +454,8 @@ pub const Err = union(enum) { |
| 455 | data.ty.displayName(ctx.ip()), | 454 | data.ty.displayName(ctx.ip()), |
| 456 | formatId( | 455 | formatId( |
| 457 | data.ty.toStructType(ctx.ip()).? | 456 | data.ty.toStructType(ctx.ip()).? |
| 458 | .field_keys[data.field].toSlice(ctx.ip()), | 457 | .field_keys.at(ctx.ip(), data.field) |
| 458 | .toSlice(ctx.ip()), | ||
| 459 | ), | 459 | ), |
| 460 | }, | 460 | }, |
| 461 | ); | 461 | ); |
| ... | @@ -872,7 +872,7 @@ fn formatItem( | ... | @@ -872,7 +872,7 @@ fn formatItem( |
| 872 | try tty.setColor(writer, .reset); | 872 | try tty.setColor(writer, .reset); |
| 873 | try tty.setColor(writer, prefix.color()); | 873 | try tty.setColor(writer, prefix.color()); |
| 874 | try tty.setColor(writer, .bold); | 874 | try tty.setColor(writer, .bold); |
| 875 | try writer.writeBytesNTimes("━", at.slice.len); | 875 | try writer.writeBytesNTimes("━", @max(at.slice.len, 1)); |
| 876 | try tty.setColor(writer, .reset); | 876 | try tty.setColor(writer, .reset); |
| 877 | try writer.writeAll("\n"); | 877 | try writer.writeAll("\n"); |
| 878 | } | 878 | } |
| ... | @@ -1074,11 +1074,10 @@ pub const Highlight = union(enum) { | ... | @@ -1074,11 +1074,10 @@ pub const Highlight = union(enum) { |
| 1074 | .byte = b, | 1074 | .byte = b, |
| 1075 | .slice = ast.utf8_source[b..][0..len], | 1075 | .slice = ast.utf8_source[b..][0..len], |
| 1076 | .loc = .{ | 1076 | .loc = .{ |
| 1077 | // TODO: | ||
| 1078 | .column = .start, | 1077 | .column = .start, |
| 1079 | .line = .start, | 1078 | .line = .start, |
| 1080 | .line_start = 0, | 1079 | .line_start = b, |
| 1081 | .line_end = @intCast(ast.utf8_source.len), | 1080 | .line_end = @intCast(b + len), |
| 1082 | }, | 1081 | }, |
| 1083 | }; | 1082 | }; |
| 1084 | }, | 1083 | }, |
src/core/Sema.zig+64-39| ... | @@ -547,7 +547,7 @@ fn stepInner(s: *Sema, comptime tag: Hir.Tag) Error!InstructionKind.fromTag(tag) | ... | @@ -547,7 +547,7 @@ fn stepInner(s: *Sema, comptime tag: Hir.Tag) Error!InstructionKind.fromTag(tag) |
| 547 | return return_type.value().toAir(); | 547 | return return_type.value().toAir(); |
| 548 | }, | 548 | }, |
| 549 | else => return s.addRef(.arg, .{ | 549 | else => return s.addRef(.arg, .{ |
| 550 | .type = proto.param_types[param.data], | 550 | .type = proto.param_types.at(s.ip, param.data), |
| 551 | .arg_number = param.data, | 551 | .arg_number = param.data, |
| 552 | }), | 552 | }), |
| 553 | } | 553 | } |
| ... | @@ -664,8 +664,8 @@ fn stepInner(s: *Sema, comptime tag: Hir.Tag) Error!InstructionKind.fromTag(tag) | ... | @@ -664,8 +664,8 @@ fn stepInner(s: *Sema, comptime tag: Hir.Tag) Error!InstructionKind.fromTag(tag) |
| 664 | } | 664 | } |
| 665 | 665 | ||
| 666 | return try s.makeValueAir(.{ .struct_type = .{ | 666 | return try s.makeValueAir(.{ .struct_type = .{ |
| 667 | .field_keys = scratch.items(.keys), | 667 | .field_keys = try s.ip.extra.appendSlice(s.gpa, scratch.items(.keys)), |
| 668 | .field_types = scratch.items(.types), | 668 | .field_types = try s.ip.extra.appendSlice(s.gpa, scratch.items(.types)), |
| 669 | } }); | 669 | } }); |
| 670 | }, | 670 | }, |
| 671 | .discard => { | 671 | .discard => { |
| ... | @@ -689,7 +689,10 @@ fn stepInner(s: *Sema, comptime tag: Hir.Tag) Error!InstructionKind.fromTag(tag) | ... | @@ -689,7 +689,10 @@ fn stepInner(s: *Sema, comptime tag: Hir.Tag) Error!InstructionKind.fromTag(tag) |
| 689 | @panic("TODO: support strings with null here"); | 689 | @panic("TODO: support strings with null here"); |
| 690 | }; | 690 | }; |
| 691 | return try s.makeValueAir(.{ .external_value = .{ | 691 | return try s.makeValueAir(.{ .external_value = .{ |
| 692 | .key = &.{str}, | 692 | .key = try s.ip.extra.appendSlice( |
| 693 | s.gpa, | ||
| 694 | @as([]const NullTerminatedString, &.{str}), | ||
| 695 | ), | ||
| 693 | } }); | 696 | } }); |
| 694 | }, | 697 | }, |
| 695 | .field => { | 698 | .field => { |
| ... | @@ -708,13 +711,13 @@ fn stepInner(s: *Sema, comptime tag: Hir.Tag) Error!InstructionKind.fromTag(tag) | ... | @@ -708,13 +711,13 @@ fn stepInner(s: *Sema, comptime tag: Hir.Tag) Error!InstructionKind.fromTag(tag) |
| 708 | const previous_key = value.toKey(s.ip).external_value.key; | 711 | const previous_key = value.toKey(s.ip).external_value.key; |
| 709 | 712 | ||
| 710 | const new_key = try std.mem.concat(s.arena(), NullTerminatedString, &.{ | 713 | const new_key = try std.mem.concat(s.arena(), NullTerminatedString, &.{ |
| 711 | previous_key, | 714 | previous_key.get(s.ip), |
| 712 | &.{field_key}, | 715 | &.{field_key}, |
| 713 | }); | 716 | }); |
| 714 | defer s.arena().free(new_key); | 717 | defer s.arena().free(new_key); |
| 715 | 718 | ||
| 716 | return s.makeValueAir(.{ .external_value = .{ | 719 | return s.makeValueAir(.{ .external_value = .{ |
| 717 | .key = new_key, | 720 | .key = try s.ip.extra.appendSlice(s.gpa, new_key), |
| 718 | } }); | 721 | } }); |
| 719 | } | 722 | } |
| 720 | } | 723 | } |
| ... | @@ -764,7 +767,11 @@ fn stepInner(s: *Sema, comptime tag: Hir.Tag) Error!InstructionKind.fromTag(tag) | ... | @@ -764,7 +767,11 @@ fn stepInner(s: *Sema, comptime tag: Hir.Tag) Error!InstructionKind.fromTag(tag) |
| 764 | } | 767 | } |
| 765 | 768 | ||
| 766 | // validate function args | 769 | // validate function args |
| 767 | for (proto.param_types, call.args.slice(&s.hir), 0..) |param, arg, i| { | 770 | for ( |
| 771 | proto.param_types.get(s.ip), | ||
| 772 | call.args.slice(&s.hir), | ||
| 773 | 0.., | ||
| 774 | ) |param, arg, i| { | ||
| 768 | const ref = s.getRef(arg, .marked); | 775 | const ref = s.getRef(arg, .marked); |
| 769 | const coerced = try s.coerceRef( | 776 | const coerced = try s.coerceRef( |
| 770 | s.lazyNode(.argument(@intCast(i))), | 777 | s.lazyNode(.argument(@intCast(i))), |
| ... | @@ -838,19 +845,23 @@ fn stepInner(s: *Sema, comptime tag: Hir.Tag) Error!InstructionKind.fromTag(tag) | ... | @@ -838,19 +845,23 @@ fn stepInner(s: *Sema, comptime tag: Hir.Tag) Error!InstructionKind.fromTag(tag) |
| 838 | for (scratch.slice(), scratch.sliceReinterpret(Value)) |ref, *value| { | 845 | for (scratch.slice(), scratch.sliceReinterpret(Value)) |ref, *value| { |
| 839 | value.* = ref.decode().value; | 846 | value.* = ref.decode().value; |
| 840 | } | 847 | } |
| 841 | return try s.makeValueAir(.{ .array_value = .{ | 848 | return try s.makeValueAir(.{ |
| 842 | .type = ty, | 849 | .array_value = .{ |
| 843 | .items = result_storage, | 850 | .type = ty, |
| 844 | } }); | 851 | // TODO: do not clone memory here |
| 852 | .items = try s.ip.extra.appendSlice(s.gpa, result_storage), | ||
| 853 | }, | ||
| 854 | }); | ||
| 845 | } else { | 855 | } else { |
| 846 | // Create a runtime array instantiation | 856 | // Create a runtime array instantiation |
| 847 | try s.ensureAtRuntime(s.lazyNode(.main_node)); | 857 | try s.ensureAtRuntime(s.lazyNode(.main_node)); |
| 848 | return try s.addRef(.array_init, .{ | 858 | return try s.addRef(.array_init, .{ |
| 849 | .ty = ty, | 859 | .ty = ty, |
| 850 | .list = try s.func.?.extra.append(s.gpa, Air.RefList, .{ | 860 | .list = try s.func.?.extra.append( |
| 851 | .start = try s.func.?.extra.appendSlice(s.gpa, scratch.slice()), | 861 | s.gpa, |
| 852 | .len = node.list.len, | 862 | Air.RefList, |
| 853 | }), | 863 | try s.func.?.extra.appendSlice(s.gpa, scratch.slice()), |
| 864 | ), | ||
| 854 | }); | 865 | }); |
| 855 | } | 866 | } |
| 856 | }, | 867 | }, |
| ... | @@ -1017,7 +1028,7 @@ fn stepInner(s: *Sema, comptime tag: Hir.Tag) Error!InstructionKind.fromTag(tag) | ... | @@ -1017,7 +1028,7 @@ fn stepInner(s: *Sema, comptime tag: Hir.Tag) Error!InstructionKind.fromTag(tag) |
| 1017 | const brk: Hir.Break = s.frame.currentPayload(.@"break"); | 1028 | const brk: Hir.Break = s.frame.currentPayload(.@"break"); |
| 1018 | const operand = s.getRef(brk.operand, .marked); | 1029 | const operand = s.getRef(brk.operand, .marked); |
| 1019 | 1030 | ||
| 1020 | assert(s.frame.block_index == brk.block); | 1031 | if (s.frame.block_index != brk.block) @panic("TODO"); |
| 1021 | 1032 | ||
| 1022 | const mark = core.U32Stack.Mark{ .stack = &s.scratch, .index = s.frame.mark_index }; | 1033 | const mark = core.U32Stack.Mark{ .stack = &s.scratch, .index = s.frame.mark_index }; |
| 1023 | 1034 | ||
| ... | @@ -1028,7 +1039,7 @@ fn stepInner(s: *Sema, comptime tag: Hir.Tag) Error!InstructionKind.fromTag(tag) | ... | @@ -1028,7 +1039,7 @@ fn stepInner(s: *Sema, comptime tag: Hir.Tag) Error!InstructionKind.fromTag(tag) |
| 1028 | const coerced = if (proto.return_type) |return_coercion| | 1039 | const coerced = if (proto.return_type) |return_coercion| |
| 1029 | try s.coerceRef(s.lazyNode(.operand), operand, return_coercion) | 1040 | try s.coerceRef(s.lazyNode(.operand), operand, return_coercion) |
| 1030 | else | 1041 | else |
| 1031 | operand; | 1042 | try s.ensureRefRuntime(s.lazyNode(.operand), operand); |
| 1032 | s.inst_map.add(s.frame.block_index, coerced); | 1043 | s.inst_map.add(s.frame.block_index, coerced); |
| 1033 | 1044 | ||
| 1034 | const indexes = mark.slice(u32); | 1045 | const indexes = mark.slice(u32); |
| ... | @@ -1388,7 +1399,7 @@ fn stepInner(s: *Sema, comptime tag: Hir.Tag) Error!InstructionKind.fromTag(tag) | ... | @@ -1388,7 +1399,7 @@ fn stepInner(s: *Sema, comptime tag: Hir.Tag) Error!InstructionKind.fromTag(tag) |
| 1388 | // may be different than the instantiation. The fields are visited in | 1399 | // may be different than the instantiation. The fields are visited in |
| 1389 | // order of the instantiation. | 1400 | // order of the instantiation. |
| 1390 | for (node.keys(&s.hir), node.inits(&s.hir), 0..) |init_key, init_value, i| { | 1401 | for (node.keys(&s.hir), node.inits(&s.hir), 0..) |init_key, init_value, i| { |
| 1391 | const found_index = index: for (struct_type.field_keys, 0..) |decl_key, j| { | 1402 | const found_index = index: for (struct_type.field_keys.get(s.ip), 0..) |decl_key, j| { |
| 1392 | if (decl_key.eqlSlice(init_key.slice(s.hir.string_bytes), s.ip)) | 1403 | if (decl_key.eqlSlice(init_key.slice(s.hir.string_bytes), s.ip)) |
| 1393 | break :index j; | 1404 | break :index j; |
| 1394 | } else { | 1405 | } else { |
| ... | @@ -1410,7 +1421,7 @@ fn stepInner(s: *Sema, comptime tag: Hir.Tag) Error!InstructionKind.fromTag(tag) | ... | @@ -1410,7 +1421,7 @@ fn stepInner(s: *Sema, comptime tag: Hir.Tag) Error!InstructionKind.fromTag(tag) |
| 1410 | const coerced = s.getCoercedRef( | 1421 | const coerced = s.getCoercedRef( |
| 1411 | s.lazyNode(.argument(@intCast(i))), | 1422 | s.lazyNode(.argument(@intCast(i))), |
| 1412 | init_value, | 1423 | init_value, |
| 1413 | struct_type.field_types[found_index], | 1424 | struct_type.field_types.at(s.ip, found_index), |
| 1414 | .marked, | 1425 | .marked, |
| 1415 | ) catch |e| switch (e) { | 1426 | ) catch |e| switch (e) { |
| 1416 | error.AnalysisFail => { | 1427 | error.AnalysisFail => { |
| ... | @@ -1452,7 +1463,7 @@ fn stepInner(s: *Sema, comptime tag: Hir.Tag) Error!InstructionKind.fromTag(tag) | ... | @@ -1452,7 +1463,7 @@ fn stepInner(s: *Sema, comptime tag: Hir.Tag) Error!InstructionKind.fromTag(tag) |
| 1452 | } | 1463 | } |
| 1453 | return try s.makeValueAir(.{ .struct_value = .{ | 1464 | return try s.makeValueAir(.{ .struct_value = .{ |
| 1454 | .ty = ty, | 1465 | .ty = ty, |
| 1455 | .field_values = result_storage, | 1466 | .field_values = try s.ip.extra.appendSlice(s.gpa, result_storage), |
| 1456 | } }); | 1467 | } }); |
| 1457 | } else { | 1468 | } else { |
| 1458 | try s.ensureAtRuntime(s.lazyNode(.main_node)); | 1469 | try s.ensureAtRuntime(s.lazyNode(.main_node)); |
| ... | @@ -1460,7 +1471,7 @@ fn stepInner(s: *Sema, comptime tag: Hir.Tag) Error!InstructionKind.fromTag(tag) | ... | @@ -1460,7 +1471,7 @@ fn stepInner(s: *Sema, comptime tag: Hir.Tag) Error!InstructionKind.fromTag(tag) |
| 1460 | const value_index = try s.func.?.extra.appendSlice(s.gpa, scratch.slice()); | 1471 | const value_index = try s.func.?.extra.appendSlice(s.gpa, scratch.slice()); |
| 1461 | return try s.addRef(.struct_init, .{ | 1472 | return try s.addRef(.struct_init, .{ |
| 1462 | .ty = ty, | 1473 | .ty = ty, |
| 1463 | .field_values = value_index, | 1474 | .field_values = value_index.start, |
| 1464 | }); | 1475 | }); |
| 1465 | } | 1476 | } |
| 1466 | }, | 1477 | }, |
| ... | @@ -1481,7 +1492,9 @@ fn stepInner(s: *Sema, comptime tag: Hir.Tag) Error!InstructionKind.fromTag(tag) | ... | @@ -1481,7 +1492,9 @@ fn stepInner(s: *Sema, comptime tag: Hir.Tag) Error!InstructionKind.fromTag(tag) |
| 1481 | dst.* = try s.getType(s.lazyNode(.argument(@intCast(i))), src); | 1492 | dst.* = try s.getType(s.lazyNode(.argument(@intCast(i))), src); |
| 1482 | } | 1493 | } |
| 1483 | 1494 | ||
| 1484 | return s.makeValueAir(.{ .tuple_type = .{ .items = scratch.slice() } }); | 1495 | return s.makeValueAir(.{ .tuple_type = .{ |
| 1496 | .items = try s.ip.extra.appendSlice(s.gpa, scratch.slice()), | ||
| 1497 | } }); | ||
| 1485 | }, | 1498 | }, |
| 1486 | 1499 | ||
| 1487 | .tuple_init => { | 1500 | .tuple_init => { |
| ... | @@ -1515,7 +1528,12 @@ fn stepInner(s: *Sema, comptime tag: Hir.Tag) Error!InstructionKind.fromTag(tag) | ... | @@ -1515,7 +1528,12 @@ fn stepInner(s: *Sema, comptime tag: Hir.Tag) Error!InstructionKind.fromTag(tag) |
| 1515 | ty.* = s.typeOfRef(val); | 1528 | ty.* = s.typeOfRef(val); |
| 1516 | } | 1529 | } |
| 1517 | 1530 | ||
| 1518 | break :ty try s.makeType(.{ .tuple_type = .{ .items = type_scratch.slice() } }); | 1531 | break :ty try s.makeType(.{ |
| 1532 | .tuple_type = .{ | ||
| 1533 | // TODO: memory leak | ||
| 1534 | .items = try s.ip.extra.appendSlice(s.gpa, type_scratch.slice()), | ||
| 1535 | }, | ||
| 1536 | }); | ||
| 1519 | }; | 1537 | }; |
| 1520 | 1538 | ||
| 1521 | if (is_const) { | 1539 | if (is_const) { |
| ... | @@ -1525,14 +1543,17 @@ fn stepInner(s: *Sema, comptime tag: Hir.Tag) Error!InstructionKind.fromTag(tag) | ... | @@ -1525,14 +1543,17 @@ fn stepInner(s: *Sema, comptime tag: Hir.Tag) Error!InstructionKind.fromTag(tag) |
| 1525 | value.* = ref.decode().value; | 1543 | value.* = ref.decode().value; |
| 1526 | } | 1544 | } |
| 1527 | 1545 | ||
| 1528 | return try s.makeValueAir(.{ .tuple_value = .{ | 1546 | return try s.makeValueAir(.{ |
| 1529 | .items = result_storage, | 1547 | .tuple_value = .{ |
| 1530 | .type = ty, | 1548 | // TODO: memory leak |
| 1531 | } }); | 1549 | .items = try s.ip.extra.appendSlice(s.gpa, result_storage), |
| 1550 | .type = ty, | ||
| 1551 | }, | ||
| 1552 | }); | ||
| 1532 | } else { | 1553 | } else { |
| 1533 | const value_index = try s.func.?.extra.appendSlice(s.gpa, scratch.slice()); | 1554 | const value_index = try s.func.?.extra.appendSlice(s.gpa, scratch.slice()); |
| 1534 | return try s.addRef(.struct_init, .{ | 1555 | return try s.addRef(.struct_init, .{ |
| 1535 | .field_values = value_index, | 1556 | .field_values = value_index.start, |
| 1536 | .ty = ty, | 1557 | .ty = ty, |
| 1537 | }); | 1558 | }); |
| 1538 | } | 1559 | } |
| ... | @@ -1550,7 +1571,7 @@ fn stepInner(s: *Sema, comptime tag: Hir.Tag) Error!InstructionKind.fromTag(tag) | ... | @@ -1550,7 +1571,7 @@ fn stepInner(s: *Sema, comptime tag: Hir.Tag) Error!InstructionKind.fromTag(tag) |
| 1550 | if (result.argument >= func.param_types.len) | 1571 | if (result.argument >= func.param_types.len) |
| 1551 | return Value.opaque_type.toAir(); | 1572 | return Value.opaque_type.toAir(); |
| 1552 | 1573 | ||
| 1553 | return func.param_types[result.argument].value().toAir(); | 1574 | return func.param_types.at(s.ip, result.argument).value().toAir(); |
| 1554 | }, | 1575 | }, |
| 1555 | 1576 | ||
| 1556 | .result_type_array_value => { | 1577 | .result_type_array_value => { |
| ... | @@ -1575,7 +1596,7 @@ fn stepInner(s: *Sema, comptime tag: Hir.Tag) Error!InstructionKind.fromTag(tag) | ... | @@ -1575,7 +1596,7 @@ fn stepInner(s: *Sema, comptime tag: Hir.Tag) Error!InstructionKind.fromTag(tag) |
| 1575 | 1596 | ||
| 1576 | _ = ty; | 1597 | _ = ty; |
| 1577 | 1598 | ||
| 1578 | @panic("TODO: tuple result type resolution"); // tuples are not implemented | 1599 | @panic("TODO: tuple result type resolution"); |
| 1579 | }, | 1600 | }, |
| 1580 | 1601 | ||
| 1581 | .result_type_struct_field => { | 1602 | .result_type_struct_field => { |
| ... | @@ -1589,7 +1610,7 @@ fn stepInner(s: *Sema, comptime tag: Hir.Tag) Error!InstructionKind.fromTag(tag) | ... | @@ -1589,7 +1610,7 @@ fn stepInner(s: *Sema, comptime tag: Hir.Tag) Error!InstructionKind.fromTag(tag) |
| 1589 | return Value.opaque_type.toAir(); | 1610 | return Value.opaque_type.toAir(); |
| 1590 | 1611 | ||
| 1591 | const to_match = result.field.slice(s.hir.string_bytes); | 1612 | const to_match = result.field.slice(s.hir.string_bytes); |
| 1592 | for (struct_type.field_keys, struct_type.field_types) |k, v| { | 1613 | for (struct_type.field_keys.get(s.ip), struct_type.field_types.get(s.ip)) |k, v| { |
| 1593 | if (k.eqlSlice(to_match, s.ip)) { | 1614 | if (k.eqlSlice(to_match, s.ip)) { |
| 1594 | return v.value().toAir(); | 1615 | return v.value().toAir(); |
| 1595 | } | 1616 | } |
| ... | @@ -1857,9 +1878,14 @@ fn coerceRef(s: *Sema, src: LazyNode, ref: Air.Inst.Ref, to: Type) !Air.Inst.Ref | ... | @@ -1857,9 +1878,14 @@ fn coerceRef(s: *Sema, src: LazyNode, ref: Air.Inst.Ref, to: Type) !Air.Inst.Ref |
| 1857 | /// Same as `coerceRef` but on a compile-time known value | 1878 | /// Same as `coerceRef` but on a compile-time known value |
| 1858 | fn coerceValue(s: *Sema, src: LazyNode, value: Value, to: Type) Error!Value { | 1879 | fn coerceValue(s: *Sema, src: LazyNode, value: Value, to: Type) Error!Value { |
| 1859 | const from = value.typeOf(s.ip); | 1880 | const from = value.typeOf(s.ip); |
| 1881 | |||
| 1882 | from.assertValid(s.ip); | ||
| 1883 | to.assertValid(s.ip); | ||
| 1884 | |||
| 1860 | if (from == to) { | 1885 | if (from == to) { |
| 1861 | return value; | 1886 | return value; |
| 1862 | } | 1887 | } |
| 1888 | |||
| 1863 | switch (to) { | 1889 | switch (to) { |
| 1864 | .@"opaque" => { | 1890 | .@"opaque" => { |
| 1865 | return try s.makeValue(.{ .opaque_value = value }); | 1891 | return try s.makeValue(.{ .opaque_value = value }); |
| ... | @@ -2069,7 +2095,7 @@ fn coerceArrayValue(s: *Sema, src: LazyNode, value: Value, item_type: Type) !Val | ... | @@ -2069,7 +2095,7 @@ fn coerceArrayValue(s: *Sema, src: LazyNode, value: Value, item_type: Type) !Val |
| 2069 | 2095 | ||
| 2070 | return try s.makeValue(.{ .array_value = .{ | 2096 | return try s.makeValue(.{ .array_value = .{ |
| 2071 | .type = try s.makeType(.{ .array_type = .{ .item_type = item_type } }), | 2097 | .type = try s.makeType(.{ .array_type = .{ .item_type = item_type } }), |
| 2072 | .items = scratch.slice(), | 2098 | .items = try s.ip.extra.appendSlice(s.gpa, scratch.slice()), |
| 2073 | } }); | 2099 | } }); |
| 2074 | } | 2100 | } |
| 2075 | 2101 | ||
| ... | @@ -2096,8 +2122,8 @@ fn coerceTupleValue( | ... | @@ -2096,8 +2122,8 @@ fn coerceTupleValue( |
| 2096 | 2122 | ||
| 2097 | // This function will append new items to the intern pool, invalidating | 2123 | // This function will append new items to the intern pool, invalidating |
| 2098 | // existing ones. Copy all data into a stable slice first. | 2124 | // existing ones. Copy all data into a stable slice first. |
| 2099 | @memcpy(scratch.items(.values), tuple_value.items); | 2125 | @memcpy(scratch.items(.values), tuple_value.items.get(s.ip)); |
| 2100 | @memcpy(scratch.items(.types), target_key.items); | 2126 | @memcpy(scratch.items(.types), target_key.items.get(s.ip)); |
| 2101 | 2127 | ||
| 2102 | for (0..len) |i| { | 2128 | for (0..len) |i| { |
| 2103 | // `s.scratch` can be invalidated by having a tuple of tuples and coercing it. | 2129 | // `s.scratch` can be invalidated by having a tuple of tuples and coercing it. |
| ... | @@ -2107,7 +2133,7 @@ fn coerceTupleValue( | ... | @@ -2107,7 +2133,7 @@ fn coerceTupleValue( |
| 2107 | 2133 | ||
| 2108 | return try s.makeValue(.{ .tuple_value = .{ | 2134 | return try s.makeValue(.{ .tuple_value = .{ |
| 2109 | .type = target_type, | 2135 | .type = target_type, |
| 2110 | .items = scratch.items(.values), | 2136 | .items = try s.ip.extra.appendSlice(s.gpa, scratch.items(.values)), |
| 2111 | } }); | 2137 | } }); |
| 2112 | } | 2138 | } |
| 2113 | 2139 | ||
| ... | @@ -2205,7 +2231,7 @@ fn fieldAccessStruct( | ... | @@ -2205,7 +2231,7 @@ fn fieldAccessStruct( |
| 2205 | else => |e| return e, | 2231 | else => |e| return e, |
| 2206 | }; | 2232 | }; |
| 2207 | 2233 | ||
| 2208 | break :found_index for (struct_type.field_keys, 0..) |key, i| { | 2234 | break :found_index for (struct_type.field_keys.get(s.ip), 0..) |key, i| { |
| 2209 | if (key == lookup) | 2235 | if (key == lookup) |
| 2210 | break @as(u32, @intCast(i)); | 2236 | break @as(u32, @intCast(i)); |
| 2211 | } else null; | 2237 | } else null; |
| ... | @@ -2341,7 +2367,7 @@ fn fieldAccessTuple( | ... | @@ -2341,7 +2367,7 @@ fn fieldAccessTuple( |
| 2341 | 2367 | ||
| 2342 | switch (lhs.decode()) { | 2368 | switch (lhs.decode()) { |
| 2343 | .value => |value| { | 2369 | .value => |value| { |
| 2344 | return value.toKey(s.ip).tuple_value.items[index].toAir(); | 2370 | return value.toKey(s.ip).tuple_value.items.at(s.ip, index).toAir(); |
| 2345 | }, | 2371 | }, |
| 2346 | .index => |lhs_index| { | 2372 | .index => |lhs_index| { |
| 2347 | try s.ensureAtRuntime(s.lazyNode(.lhs)); | 2373 | try s.ensureAtRuntime(s.lazyNode(.lhs)); |
| ... | @@ -2359,11 +2385,10 @@ fn postVisitFunctionPrototype(s: *Sema, reserve: FunctionReserve, return_type: ? | ... | @@ -2359,11 +2385,10 @@ fn postVisitFunctionPrototype(s: *Sema, reserve: FunctionReserve, return_type: ? |
| 2359 | const tracked_inst = try s.ip.trackInst(s.gpa, s.file, s.frame.currentIndex()); | 2385 | const tracked_inst = try s.ip.trackInst(s.gpa, s.file, s.frame.currentIndex()); |
| 2360 | const func_type = try s.makeType(.{ | 2386 | const func_type = try s.makeType(.{ |
| 2361 | .function_type = .{ | 2387 | .function_type = .{ |
| 2362 | .param_types = reserve.items(.params), | 2388 | .param_types = try s.ip.extra.appendSlice(s.gpa, reserve.items(.params)), |
| 2363 | .return_type = return_type, | 2389 | .return_type = return_type, |
| 2364 | }, | 2390 | }, |
| 2365 | }); | 2391 | }); |
| 2366 | // TODO: make a dedicated function to insert a new function | ||
| 2367 | const func_value = try s.makeValue(.{ | 2392 | const func_value = try s.makeValue(.{ |
| 2368 | .func = .{ | 2393 | .func = .{ |
| 2369 | .ty = func_type, | 2394 | .ty = func_type, |
src/core/array.zig+122-72| ... | @@ -81,24 +81,14 @@ pub const StoreKind = enum { | ... | @@ -81,24 +81,14 @@ pub const StoreKind = enum { |
| 81 | air, | 81 | air, |
| 82 | js_tree, | 82 | js_tree, |
| 83 | 83 | ||
| 84 | pub fn resolveStoreConst( | 84 | pub fn resolveStore( |
| 85 | comptime kind: StoreKind, | 85 | comptime kind: StoreKind, |
| 86 | owner: anytype, | 86 | owner: anytype, |
| 87 | ) *const kind.ResolvedStore(@TypeOf(owner)) { | 87 | ) kind.ResolvedStorePtr(@TypeOf(owner)) { |
| 88 | return &owner.extra; | 88 | return &owner.extra; |
| 89 | } | 89 | } |
| 90 | 90 | ||
| 91 | pub fn resolveStoreMut( | 91 | pub fn ResolvedStore(kind: StoreKind, Owner: type) type { |
| 92 | comptime kind: StoreKind, | ||
| 93 | owner: anytype, | ||
| 94 | ) *kind.ResolvedStore(@TypeOf(owner)) { | ||
| 95 | return &owner.extra; | ||
| 96 | } | ||
| 97 | |||
| 98 | pub fn ResolvedStore( | ||
| 99 | comptime kind: StoreKind, | ||
| 100 | comptime Owner: type, | ||
| 101 | ) type { | ||
| 102 | const ptr = @typeInfo(Owner).pointer; | 92 | const ptr = @typeInfo(Owner).pointer; |
| 103 | assert(ptr.size == .One); | 93 | assert(ptr.size == .One); |
| 104 | const mutability = brk: for (@typeInfo(ptr.child).@"struct".fields) |field| { | 94 | const mutability = brk: for (@typeInfo(ptr.child).@"struct".fields) |field| { |
| ... | @@ -108,42 +98,32 @@ pub const StoreKind = enum { | ... | @@ -108,42 +98,32 @@ pub const StoreKind = enum { |
| 108 | } else unreachable; | 98 | } else unreachable; |
| 109 | return ExtraStore(kind, mutability); | 99 | return ExtraStore(kind, mutability); |
| 110 | } | 100 | } |
| 111 | }; | ||
| 112 | |||
| 113 | fn ExtraWrap(comptime kind: StoreKind) type { | ||
| 114 | return struct { | ||
| 115 | pub fn Index(comptime T: type) type { | ||
| 116 | return enum(u32) { | ||
| 117 | _, | ||
| 118 | 101 | ||
| 119 | pub fn get(index: @This(), owner: anytype) T { | 102 | pub fn ResolvedStorePtr(kind: StoreKind, Owner: type) type { |
| 120 | return kind.resolveStoreConst(owner).get(T, @intFromEnum(index)); | 103 | return kind.ItemPointer(Owner, .One, kind.ResolvedStore(Owner)); |
| 121 | } | 104 | } |
| 122 | |||
| 123 | pub fn set(index: @This(), owner: anytype, payload: T) void { | ||
| 124 | return kind.resolveStoreMut(owner).set(T, @intFromEnum(index), payload); | ||
| 125 | } | ||
| 126 | |||
| 127 | /// Returns data with a trailing reader to read data stored immediately after | ||
| 128 | /// the main data structure. What is stored should be documented on `T` | ||
| 129 | pub fn getTrail(index: @This(), owner: anytype) struct { | ||
| 130 | T, | ||
| 131 | kind.ResolvedStore(@TypeOf(owner)).TrailReader, | ||
| 132 | } { | ||
| 133 | const advance = comptime extraSizeOf(T); | ||
| 134 | return .{ | ||
| 135 | index.get(owner), | ||
| 136 | .{ .index = @intFromEnum(index) + advance }, | ||
| 137 | }; | ||
| 138 | } | ||
| 139 | 105 | ||
| 140 | pub fn jsonStringify(index: @This(), jw: anytype) !void { | 106 | pub fn ItemPointer( |
| 141 | try jw.write(@intFromEnum(index)); | 107 | kind: StoreKind, |
| 142 | } | 108 | Owner: type, |
| 143 | }; | 109 | size: std.builtin.Type.Pointer.Size, |
| 144 | } | 110 | child: type, |
| 145 | }; | 111 | ) type { |
| 146 | } | 112 | const ptr = @typeInfo(Owner).pointer; |
| 113 | return @Type(.{ | ||
| 114 | .pointer = .{ | ||
| 115 | .size = size, | ||
| 116 | .is_const = ptr.is_const or ResolvedStore(kind, Owner).mutability == .@"const", | ||
| 117 | .is_volatile = false, | ||
| 118 | .is_allowzero = false, | ||
| 119 | .alignment = @alignOf(child), | ||
| 120 | .address_space = .generic, | ||
| 121 | .child = child, | ||
| 122 | .sentinel = null, | ||
| 123 | }, | ||
| 124 | }); | ||
| 125 | } | ||
| 126 | }; | ||
| 147 | 127 | ||
| 148 | pub fn EncodedData(comptime Tag: type, backing_type: type) type { | 128 | pub fn EncodedData(comptime Tag: type, backing_type: type) type { |
| 149 | return enum(backing_type) { | 129 | return enum(backing_type) { |
| ... | @@ -230,23 +210,89 @@ pub inline fn extraSizeOf(comptime T: type) usize { | ... | @@ -230,23 +210,89 @@ pub inline fn extraSizeOf(comptime T: type) usize { |
| 230 | }; | 210 | }; |
| 231 | } | 211 | } |
| 232 | 212 | ||
| 233 | // TODO: rename to Store | 213 | pub const ExtraStore = Store; |
| 234 | pub fn ExtraStore(comptime set_kind: StoreKind, comptime set_mutability: Mutability) type { | 214 | |
| 215 | /// A data structure to manage a `[]u32` with mixed data types. Provides | ||
| 216 | /// `.Index` and `.Slice` to keep strongly typed indices to items within the | ||
| 217 | /// store. | ||
| 218 | pub fn Store(set_kind: StoreKind, set_mutability: Mutability) type { | ||
| 219 | // Separate struct to avoid capturing set_mutability | ||
| 220 | const wrappers = struct { | ||
| 221 | pub const kind = set_kind; | ||
| 222 | |||
| 223 | pub fn Index(T: type) type { | ||
| 224 | return enum(u32) { | ||
| 225 | _, | ||
| 226 | |||
| 227 | pub fn get(index: @This(), owner: anytype) T { | ||
| 228 | return kind.resolveStore(owner).get(T, @intFromEnum(index)); | ||
| 229 | } | ||
| 230 | |||
| 231 | pub fn set(index: @This(), owner: anytype, payload: T) void { | ||
| 232 | return kind.resolveStore(owner).set(T, @intFromEnum(index), payload); | ||
| 233 | } | ||
| 234 | |||
| 235 | /// Returns data with a trailing reader to read data stored immediately after | ||
| 236 | /// the main data structure. What is stored should be documented on `T` | ||
| 237 | pub fn getTrail(index: @This(), owner: anytype) struct { | ||
| 238 | T, | ||
| 239 | kind.ResolvedStore(@TypeOf(owner)).TrailReader, | ||
| 240 | } { | ||
| 241 | const advance = comptime extraSizeOf(T); | ||
| 242 | return .{ | ||
| 243 | index.get(owner), | ||
| 244 | .{ .index = @intFromEnum(index) + advance }, | ||
| 245 | }; | ||
| 246 | } | ||
| 247 | |||
| 248 | pub fn jsonStringify(index: @This(), jw: anytype) !void { | ||
| 249 | try jw.write(@intFromEnum(index)); | ||
| 250 | } | ||
| 251 | }; | ||
| 252 | } | ||
| 253 | |||
| 254 | /// An array of `T` existing within the `extra` array. | ||
| 255 | /// This type exists to provide a struct with lifetime that is | ||
| 256 | /// not invalidated when items are added to the `InternPool`. | ||
| 257 | pub fn Slice(T: type) type { | ||
| 258 | return struct { | ||
| 259 | start: u32, | ||
| 260 | len: u32, | ||
| 261 | |||
| 262 | pub const empty: @This() = .{ | ||
| 263 | .start = 0, | ||
| 264 | .len = 0, | ||
| 265 | }; | ||
| 266 | |||
| 267 | pub fn get(slice: @This(), owner: anytype) kind.ItemPointer(@TypeOf(owner), .Slice, T) { | ||
| 268 | return @ptrCast(kind.resolveStore(owner).list.items[slice.start..][0..slice.len]); | ||
| 269 | } | ||
| 270 | |||
| 271 | pub fn at(slice: @This(), owner: anytype, index: usize) T { | ||
| 272 | return slice.get(owner)[index]; | ||
| 273 | } | ||
| 274 | }; | ||
| 275 | } | ||
| 276 | }; | ||
| 277 | |||
| 235 | return struct { | 278 | return struct { |
| 236 | list: List = .{}, | 279 | const Self = @This(); |
| 280 | |||
| 281 | list: Inner, | ||
| 237 | 282 | ||
| 238 | pub const empty: @This() = .{}; | 283 | pub const empty: @This() = .{ .list = .empty }; |
| 239 | 284 | ||
| 240 | pub const kind = set_kind; | 285 | pub const kind = set_kind; |
| 241 | pub const mutability = set_mutability; | 286 | pub const mutability = set_mutability; |
| 242 | 287 | ||
| 243 | const Store = @This(); | 288 | pub const Index = wrappers.Index; |
| 244 | 289 | pub const Slice = wrappers.Slice; | |
| 245 | pub const Index = ExtraWrap(kind).Index; | ||
| 246 | 290 | ||
| 247 | pub const List = switch (mutability) { | 291 | pub const Inner = switch (mutability) { |
| 248 | .@"const" => struct { | 292 | .@"const" => struct { |
| 249 | items: []const u32 = &.{}, | 293 | items: []const u32, |
| 294 | |||
| 295 | pub const empty = .{ .items = &.{} }; | ||
| 250 | 296 | ||
| 251 | pub fn deinit(slice: *@This(), gpa: Allocator) void { | 297 | pub fn deinit(slice: *@This(), gpa: Allocator) void { |
| 252 | gpa.free(slice.items); | 298 | gpa.free(slice.items); |
| ... | @@ -255,7 +301,7 @@ pub fn ExtraStore(comptime set_kind: StoreKind, comptime set_mutability: Mutabil | ... | @@ -255,7 +301,7 @@ pub fn ExtraStore(comptime set_kind: StoreKind, comptime set_mutability: Mutabil |
| 255 | .@"var" => std.ArrayListUnmanaged(u32), | 301 | .@"var" => std.ArrayListUnmanaged(u32), |
| 256 | }; | 302 | }; |
| 257 | 303 | ||
| 258 | pub fn deinit(store: *Store, gpa: Allocator) void { | 304 | pub fn deinit(store: *Self, gpa: Allocator) void { |
| 259 | store.list.deinit(gpa); | 305 | store.list.deinit(gpa); |
| 260 | store.* = undefined; | 306 | store.* = undefined; |
| 261 | } | 307 | } |
| ... | @@ -263,12 +309,12 @@ pub fn ExtraStore(comptime set_kind: StoreKind, comptime set_mutability: Mutabil | ... | @@ -263,12 +309,12 @@ pub fn ExtraStore(comptime set_kind: StoreKind, comptime set_mutability: Mutabil |
| 263 | pub const TrailReader = struct { | 309 | pub const TrailReader = struct { |
| 264 | index: usize, | 310 | index: usize, |
| 265 | 311 | ||
| 266 | pub fn read(trail: *TrailReader, ip: *const Store, comptime T: type) T { | 312 | pub fn read(trail: *TrailReader, ip: *const Self, comptime T: type) T { |
| 267 | defer trail.index += comptime extraSizeOf(T); | 313 | defer trail.index += comptime extraSizeOf(T); |
| 268 | return ip.get(T, trail.index); | 314 | return ip.get(T, trail.index); |
| 269 | } | 315 | } |
| 270 | 316 | ||
| 271 | pub fn at(trail: *const TrailReader, ip: *const Store, comptime T: type, index: u32) T { | 317 | pub fn at(trail: *const TrailReader, ip: *const Self, comptime T: type, index: u32) T { |
| 272 | return ip.get(T, trail.index + index); | 318 | return ip.get(T, trail.index + index); |
| 273 | } | 319 | } |
| 274 | 320 | ||
| ... | @@ -301,10 +347,10 @@ pub fn ExtraStore(comptime set_kind: StoreKind, comptime set_mutability: Mutabil | ... | @@ -301,10 +347,10 @@ pub fn ExtraStore(comptime set_kind: StoreKind, comptime set_mutability: Mutabil |
| 301 | }; | 347 | }; |
| 302 | 348 | ||
| 303 | pub const TrailWriter = struct { | 349 | pub const TrailWriter = struct { |
| 304 | store: *Store, | 350 | store: *Self, |
| 305 | leftover: usize, | 351 | leftover: usize, |
| 306 | 352 | ||
| 307 | pub fn init(store: *Store, len: usize) TrailWriter { | 353 | pub fn init(store: *Self, len: usize) TrailWriter { |
| 308 | return .{ .store = store, .leftover = len }; | 354 | return .{ .store = store, .leftover = len }; |
| 309 | } | 355 | } |
| 310 | 356 | ||
| ... | @@ -332,13 +378,13 @@ pub fn ExtraStore(comptime set_kind: StoreKind, comptime set_mutability: Mutabil | ... | @@ -332,13 +378,13 @@ pub fn ExtraStore(comptime set_kind: StoreKind, comptime set_mutability: Mutabil |
| 332 | } | 378 | } |
| 333 | }; | 379 | }; |
| 334 | 380 | ||
| 335 | pub fn append(store: *Store, gpa: Allocator, comptime T: type, payload: T) Allocator.Error!Index(T) { | 381 | pub fn append(store: *Self, gpa: Allocator, comptime T: type, payload: T) Allocator.Error!Index(T) { |
| 336 | comptime assert(mutability == .@"var"); | 382 | comptime assert(mutability == .@"var"); |
| 337 | try store.list.ensureUnusedCapacity(gpa, extraSizeOf(@TypeOf(payload))); | 383 | try store.list.ensureUnusedCapacity(gpa, extraSizeOf(@TypeOf(payload))); |
| 338 | return store.appendAssumeCapacity(T, payload); | 384 | return store.appendAssumeCapacity(T, payload); |
| 339 | } | 385 | } |
| 340 | 386 | ||
| 341 | pub fn appendAssumeCapacity(ip: *Store, comptime T: type, payload: T) Index(T) { | 387 | pub fn appendAssumeCapacity(ip: *Self, comptime T: type, payload: T) Index(T) { |
| 342 | comptime assert(mutability == .@"var"); | 388 | comptime assert(mutability == .@"var"); |
| 343 | const extra_index: u32 = @intCast(ip.list.items.len); | 389 | const extra_index: u32 = @intCast(ip.list.items.len); |
| 344 | ip.list.items.len += extraSizeOf(@TypeOf(payload)); | 390 | ip.list.items.len += extraSizeOf(@TypeOf(payload)); |
| ... | @@ -347,7 +393,7 @@ pub fn ExtraStore(comptime set_kind: StoreKind, comptime set_mutability: Mutabil | ... | @@ -347,7 +393,7 @@ pub fn ExtraStore(comptime set_kind: StoreKind, comptime set_mutability: Mutabil |
| 347 | } | 393 | } |
| 348 | 394 | ||
| 349 | pub fn appendTrailing( | 395 | pub fn appendTrailing( |
| 350 | store: *Store, | 396 | store: *Self, |
| 351 | gpa: Allocator, | 397 | gpa: Allocator, |
| 352 | comptime T: type, | 398 | comptime T: type, |
| 353 | payload: T, | 399 | payload: T, |
| ... | @@ -365,32 +411,34 @@ pub fn ExtraStore(comptime set_kind: StoreKind, comptime set_mutability: Mutabil | ... | @@ -365,32 +411,34 @@ pub fn ExtraStore(comptime set_kind: StoreKind, comptime set_mutability: Mutabil |
| 365 | } | 411 | } |
| 366 | 412 | ||
| 367 | // TODO: make setAsU32 allow any type | 413 | // TODO: make setAsU32 allow any type |
| 368 | pub fn setU32(store: *Store, index: usize, payload: u32) void { | 414 | pub fn setU32(store: *Self, index: usize, payload: u32) void { |
| 369 | comptime assert(mutability == .@"var"); | 415 | comptime assert(mutability == .@"var"); |
| 370 | store.list.items[index] = payload; | 416 | store.list.items[index] = payload; |
| 371 | } | 417 | } |
| 372 | 418 | ||
| 373 | pub fn set(store: *Store, comptime T: type, index: usize, payload: T) void { | 419 | pub fn set(store: *Self, comptime T: type, index: usize, payload: T) void { |
| 374 | comptime assert(mutability == .@"var"); | 420 | comptime assert(mutability == .@"var"); |
| 375 | setAsU32(store.list.items, T, index, payload); | 421 | setAsU32(store.list.items, T, index, payload); |
| 376 | } | 422 | } |
| 377 | 423 | ||
| 378 | pub fn get(store: *const Store, comptime T: type, index: usize) T { | 424 | pub fn get(store: *const Self, comptime T: type, index: usize) T { |
| 379 | return getAsU32(store.list.items, T, index); | 425 | return getAsU32(store.list.items, T, index); |
| 380 | } | 426 | } |
| 381 | 427 | ||
| 382 | pub fn toOwnedStore(store: *Store, gpa: Allocator) !ExtraStore(set_kind, .@"const") { | 428 | pub fn toOwnedStore(store: *Self, gpa: Allocator) !ExtraStore(set_kind, .@"const") { |
| 383 | comptime assert(mutability == .@"var"); | 429 | comptime assert(mutability == .@"var"); |
| 384 | return .{ .list = .{ .items = try store.list.toOwnedSlice(gpa) } }; | 430 | return .{ .list = .{ .items = try store.list.toOwnedSlice(gpa) } }; |
| 385 | } | 431 | } |
| 386 | 432 | ||
| 387 | pub fn constant(store: *const Store) ExtraStore(set_kind, .@"const") { | 433 | /// Returns a `const` store pointing at the mutable's data. |
| 434 | /// Invalidated when the mutable store is mutated. | ||
| 435 | pub fn constant(store: *const Self) ExtraStore(set_kind, .@"const") { | ||
| 388 | return .{ .list = .{ .items = store.list.items } }; | 436 | return .{ .list = .{ .items = store.list.items } }; |
| 389 | } | 437 | } |
| 390 | 438 | ||
| 391 | // TODO: Add some safety to the Index returned from this | 439 | // TODO: Add some safety to the Index returned from this |
| 392 | /// Allocate a number of u32s into this store, but they are left uninitialized. | 440 | /// Allocate a number of u32s into this store, but they are left uninitialized. |
| 393 | pub fn alloc(store: *Store, gpa: Allocator, len: usize) !u32 { | 441 | pub fn alloc(store: *Self, gpa: Allocator, len: usize) !u32 { |
| 394 | comptime assert(mutability == .@"var"); | 442 | comptime assert(mutability == .@"var"); |
| 395 | const idx = store.list.items.len; | 443 | const idx = store.list.items.len; |
| 396 | try store.list.ensureUnusedCapacity(gpa, len); | 444 | try store.list.ensureUnusedCapacity(gpa, len); |
| ... | @@ -398,13 +446,15 @@ pub fn ExtraStore(comptime set_kind: StoreKind, comptime set_mutability: Mutabil | ... | @@ -398,13 +446,15 @@ pub fn ExtraStore(comptime set_kind: StoreKind, comptime set_mutability: Mutabil |
| 398 | return @intCast(idx); | 446 | return @intCast(idx); |
| 399 | } | 447 | } |
| 400 | 448 | ||
| 401 | pub fn appendSlice(store: *Store, gpa: Allocator, data: anytype) !u32 { | 449 | pub fn appendSlice(store: *Self, gpa: Allocator, data: anytype) !Slice(std.meta.Child(@TypeOf(data))) { |
| 402 | const idx = store.list.items.len; | 450 | const idx = store.list.items.len; |
| 451 | comptime assert(@typeInfo(@TypeOf(data)).pointer.size == .Slice); | ||
| 452 | comptime assert(@typeInfo(@TypeOf(data)).pointer.alignment == @alignOf(u32)); | ||
| 403 | comptime assert(@sizeOf(@TypeOf(data[0])) == @sizeOf(u32)); | 453 | comptime assert(@sizeOf(@TypeOf(data[0])) == @sizeOf(u32)); |
| 404 | comptime assert(@alignOf(@TypeOf(data[0])) == @alignOf(u32)); | 454 | comptime assert(@alignOf(@TypeOf(data[0])) == @alignOf(u32)); |
| 405 | try store.list.appendSlice(gpa, @ptrCast(data)); | 455 | try store.list.appendSlice(gpa, @ptrCast(data)); |
| 406 | store.list.items.len += data.len; | 456 | store.list.items.len += data.len; |
| 407 | return @intCast(idx); | 457 | return .{ .start = @intCast(idx), .len = @intCast(data.len) }; |
| 408 | } | 458 | } |
| 409 | }; | 459 | }; |
| 410 | } | 460 | } |
src/core/js/Link.zig+17-8| ... | @@ -284,8 +284,9 @@ fn printValue(link: *Link, value: InternPool.Value, level: Level, writer: anytyp | ... | @@ -284,8 +284,9 @@ fn printValue(link: *Link, value: InternPool.Value, level: Level, writer: anytyp |
| 284 | try writer.writeAll("{"); | 284 | try writer.writeAll("{"); |
| 285 | 285 | ||
| 286 | for ( | 286 | for ( |
| 287 | struct_value.ty.toStructType(&link.comp.intern_pool).?.field_keys, | 287 | struct_value.ty.toStructType(&link.comp.intern_pool).? |
| 288 | struct_value.field_values, | 288 | .field_keys.get(&link.comp.intern_pool), |
| 289 | struct_value.field_values.get(&link.comp.intern_pool), | ||
| 289 | 0.., | 290 | 0.., |
| 290 | ) |key, inner_value, i| { | 291 | ) |key, inner_value, i| { |
| 291 | if (i != 0) | 292 | if (i != 0) |
| ... | @@ -305,7 +306,7 @@ fn printValue(link: *Link, value: InternPool.Value, level: Level, writer: anytyp | ... | @@ -305,7 +306,7 @@ fn printValue(link: *Link, value: InternPool.Value, level: Level, writer: anytyp |
| 305 | .array_value => |array_value| { | 306 | .array_value => |array_value| { |
| 306 | try writer.writeAll("["); | 307 | try writer.writeAll("["); |
| 307 | 308 | ||
| 308 | for (array_value.items, 0..) |inner_value, i| { | 309 | for (array_value.items.get(&link.comp.intern_pool), 0..) |inner_value, i| { |
| 309 | if (i != 0) | 310 | if (i != 0) |
| 310 | try writer.writeAll(","); | 311 | try writer.writeAll(","); |
| 311 | 312 | ||
| ... | @@ -317,7 +318,7 @@ fn printValue(link: *Link, value: InternPool.Value, level: Level, writer: anytyp | ... | @@ -317,7 +318,7 @@ fn printValue(link: *Link, value: InternPool.Value, level: Level, writer: anytyp |
| 317 | .tuple_value => |tuple_value| { | 318 | .tuple_value => |tuple_value| { |
| 318 | try writer.writeAll("["); | 319 | try writer.writeAll("["); |
| 319 | 320 | ||
| 320 | for (tuple_value.items, 0..) |inner_value, i| { | 321 | for (tuple_value.items.get(&link.comp.intern_pool), 0..) |inner_value, i| { |
| 321 | if (i != 0) | 322 | if (i != 0) |
| 322 | try writer.writeAll(","); | 323 | try writer.writeAll(","); |
| 323 | 324 | ||
| ... | @@ -327,7 +328,7 @@ fn printValue(link: *Link, value: InternPool.Value, level: Level, writer: anytyp | ... | @@ -327,7 +328,7 @@ fn printValue(link: *Link, value: InternPool.Value, level: Level, writer: anytyp |
| 327 | }, | 328 | }, |
| 328 | 329 | ||
| 329 | .external_value => |external_value| { | 330 | .external_value => |external_value| { |
| 330 | for (external_value.key, 0..) |part, i| { | 331 | for (external_value.key.get(&link.comp.intern_pool), 0..) |part, i| { |
| 331 | if (i != 0) try writer.writeAll("."); | 332 | if (i != 0) try writer.writeAll("."); |
| 332 | try writer.writeAll(part.toSlice(&link.comp.intern_pool)); | 333 | try writer.writeAll(part.toSlice(&link.comp.intern_pool)); |
| 333 | } | 334 | } |
| ... | @@ -477,11 +478,15 @@ fn printExprLevel( | ... | @@ -477,11 +478,15 @@ fn printExprLevel( |
| 477 | }, | 478 | }, |
| 478 | 479 | ||
| 479 | .comma_chain => { | 480 | .comma_chain => { |
| 481 | if (Level.comma.needsParens(level)) | ||
| 482 | try writer.writeAll("("); | ||
| 480 | const bin: Tree.IndexList = tree.nodeData(.comma_chain, node); | 483 | const bin: Tree.IndexList = tree.nodeData(.comma_chain, node); |
| 481 | for (bin.slice(tree), 0..) |expr, i| { | 484 | for (bin.slice(tree), 0..) |expr, i| { |
| 482 | if (i != 0) try writer.writeAll(", "); | 485 | if (i != 0) try writer.writeAll(", "); |
| 483 | try link.printExprLevel(tree, expr, .assignment, writer); | 486 | try link.printExprLevel(tree, expr, .assignment, writer); |
| 484 | } | 487 | } |
| 488 | if (Level.comma.needsParens(level)) | ||
| 489 | try writer.writeAll(")"); | ||
| 485 | }, | 490 | }, |
| 486 | 491 | ||
| 487 | inline .negate, | 492 | inline .negate, |
| ... | @@ -503,9 +508,9 @@ fn printExprLevel( | ... | @@ -503,9 +508,9 @@ fn printExprLevel( |
| 503 | try writer.writeAll("("); | 508 | try writer.writeAll("("); |
| 504 | try link.printExprLevel(tree, ternary.cond, .logical_or, writer); | 509 | try link.printExprLevel(tree, ternary.cond, .logical_or, writer); |
| 505 | try writer.writeAll(" ? "); | 510 | try writer.writeAll(" ? "); |
| 506 | try link.printExpr(tree, data.yes, writer); | 511 | try link.printExprLevel(tree, data.yes, .assignment, writer); |
| 507 | try writer.writeAll(" : "); | 512 | try writer.writeAll(" : "); |
| 508 | try link.printExpr(tree, data.no, writer); | 513 | try link.printExprLevel(tree, data.no, .assignment, writer); |
| 509 | if (wrap) | 514 | if (wrap) |
| 510 | try writer.writeAll(")"); | 515 | try writer.writeAll(")"); |
| 511 | }, | 516 | }, |
| ... | @@ -518,7 +523,11 @@ fn printExprLevel( | ... | @@ -518,7 +523,11 @@ fn printExprLevel( |
| 518 | const k = tree.nodeData(.plain_value, call.base).value.toKey(&link.comp.intern_pool); | 523 | const k = tree.nodeData(.plain_value, call.base).value.toKey(&link.comp.intern_pool); |
| 519 | break :brk k == .external_value and | 524 | break :brk k == .external_value and |
| 520 | k.external_value.key.len == 1 and | 525 | k.external_value.key.len == 1 and |
| 521 | std.mem.eql(u8, k.external_value.key[0].toSlice(&link.comp.intern_pool), "eval"); | 526 | std.mem.eql( |
| 527 | u8, | ||
| 528 | k.external_value.key.at(&link.comp.intern_pool, 0).toSlice(&link.comp.intern_pool), | ||
| 529 | "eval", | ||
| 530 | ); | ||
| 522 | }) { | 531 | }) { |
| 523 | @branchHint(.unlikely); | 532 | @branchHint(.unlikely); |
| 524 | try writer.writeAll("(0, eval)"); | 533 | try writer.writeAll("(0, eval)"); |
src/core/js/NodeGen.zig+19-14| ... | @@ -47,8 +47,8 @@ pub fn init(gpa: Allocator, arena: Allocator, ip: *InternPool, air: Air) !NodeGe | ... | @@ -47,8 +47,8 @@ pub fn init(gpa: Allocator, arena: Allocator, ip: *InternPool, air: Air) !NodeGe |
| 47 | .extern_symbols = .{}, | 47 | .extern_symbols = .{}, |
| 48 | .top_level_value_deps = .{}, | 48 | .top_level_value_deps = .{}, |
| 49 | .air_node_map = air_node_map, | 49 | .air_node_map = air_node_map, |
| 50 | .extra = .{}, | 50 | .extra = .empty, |
| 51 | .scratch = .{}, | 51 | .scratch = .empty, |
| 52 | .next_id = param_count, | 52 | .next_id = param_count, |
| 53 | .next_label = 0, | 53 | .next_label = 0, |
| 54 | }; | 54 | }; |
| ... | @@ -100,7 +100,7 @@ pub fn build(c: *NodeGen) !void { | ... | @@ -100,7 +100,7 @@ pub fn build(c: *NodeGen) !void { |
| 100 | defer t.end(); | 100 | defer t.end(); |
| 101 | 101 | ||
| 102 | assert(c.air.instTag(.main_block) == .block); // expected Air to start with block | 102 | assert(c.air.instTag(.main_block) == .block); // expected Air to start with block |
| 103 | const statements = c.air.instData(.block, .main_block).slice(&c.air); | 103 | const statements = c.air.instData(.block, .main_block).get(&c.air); |
| 104 | 104 | ||
| 105 | const scratch_top = c.scratch.items.len; | 105 | const scratch_top = c.scratch.items.len; |
| 106 | defer c.scratch.shrinkRetainingCapacity(scratch_top); | 106 | defer c.scratch.shrinkRetainingCapacity(scratch_top); |
| ... | @@ -301,7 +301,7 @@ fn codeGenInst(c: *NodeGen, inst: Air.Inst.Index) Error!void { | ... | @@ -301,7 +301,7 @@ fn codeGenInst(c: *NodeGen, inst: Air.Inst.Index) Error!void { |
| 301 | .field = field_name: { | 301 | .field = field_name: { |
| 302 | break :field_name c.air.typeOfIndex(data.base, c.ip) | 302 | break :field_name c.air.typeOfIndex(data.base, c.ip) |
| 303 | .toStructType(c.ip).? | 303 | .toStructType(c.ip).? |
| 304 | .field_keys[data.field_index]; | 304 | .field_keys.at(c.ip, data.field_index); |
| 305 | }, | 305 | }, |
| 306 | }); | 306 | }); |
| 307 | try c.markExpression(inst, node); | 307 | try c.markExpression(inst, node); |
| ... | @@ -338,7 +338,7 @@ fn codeGenInst(c: *NodeGen, inst: Air.Inst.Index) Error!void { | ... | @@ -338,7 +338,7 @@ fn codeGenInst(c: *NodeGen, inst: Air.Inst.Index) Error!void { |
| 338 | 338 | ||
| 339 | const items = c.extra.list.items[start..][0..call_data.args.len]; | 339 | const items = c.extra.list.items[start..][0..call_data.args.len]; |
| 340 | 340 | ||
| 341 | for (call_data.args.slice(&c.air), items) |arg, *dest| { | 341 | for (call_data.args.get(&c.air), items) |arg, *dest| { |
| 342 | dest.* = @intFromEnum(try c.fetchExpression(arg)); | 342 | dest.* = @intFromEnum(try c.fetchExpression(arg)); |
| 343 | } | 343 | } |
| 344 | 344 | ||
| ... | @@ -457,7 +457,7 @@ fn codeGenInst(c: *NodeGen, inst: Air.Inst.Index) Error!void { | ... | @@ -457,7 +457,7 @@ fn codeGenInst(c: *NodeGen, inst: Air.Inst.Index) Error!void { |
| 457 | // | 457 | // |
| 458 | // This is also required for the main function, which cannot return | 458 | // This is also required for the main function, which cannot return |
| 459 | // anything. We don't want to emit return instructions here. | 459 | // anything. We don't want to emit return instructions here. |
| 460 | const main_insts = c.air.instData(.block, .main_block).slice(&c.air); | 460 | const main_insts = c.air.instData(.block, .main_block).get(&c.air); |
| 461 | if (main_insts[main_insts.len - 1] == inst) { | 461 | if (main_insts[main_insts.len - 1] == inst) { |
| 462 | return; | 462 | return; |
| 463 | } | 463 | } |
| ... | @@ -472,7 +472,7 @@ fn codeGenInst(c: *NodeGen, inst: Air.Inst.Index) Error!void { | ... | @@ -472,7 +472,7 @@ fn codeGenInst(c: *NodeGen, inst: Air.Inst.Index) Error!void { |
| 472 | const operand = try c.fetchExpression(brk.value); | 472 | const operand = try c.fetchExpression(brk.value); |
| 473 | const block = &c.air_node_map[@intFromEnum(brk.block)].block; | 473 | const block = &c.air_node_map[@intFromEnum(brk.block)].block; |
| 474 | 474 | ||
| 475 | const block_insts = c.air.instData(.block, brk.block).slice(&c.air); | 475 | const block_insts = c.air.instData(.block, brk.block).get(&c.air); |
| 476 | if (block_insts[block_insts.len - 1] != inst) { | 476 | if (block_insts[block_insts.len - 1] != inst) { |
| 477 | block.used = true; | 477 | block.used = true; |
| 478 | } | 478 | } |
| ... | @@ -499,7 +499,7 @@ fn codeGenInst(c: *NodeGen, inst: Air.Inst.Index) Error!void { | ... | @@ -499,7 +499,7 @@ fn codeGenInst(c: *NodeGen, inst: Air.Inst.Index) Error!void { |
| 499 | const store_offset = try c.extra.alloc(c.gpa, property_count * 2); | 499 | const store_offset = try c.extra.alloc(c.gpa, property_count * 2); |
| 500 | 500 | ||
| 501 | for ( | 501 | for ( |
| 502 | struct_type.field_keys, | 502 | struct_type.field_keys.get(c.ip), |
| 503 | struct_init.valuesPtr(&c.air), | 503 | struct_init.valuesPtr(&c.air), |
| 504 | store_offset.., | 504 | store_offset.., |
| 505 | store_offset + property_count.., | 505 | store_offset + property_count.., |
| ... | @@ -520,7 +520,7 @@ fn codeGenInst(c: *NodeGen, inst: Air.Inst.Index) Error!void { | ... | @@ -520,7 +520,7 @@ fn codeGenInst(c: *NodeGen, inst: Air.Inst.Index) Error!void { |
| 520 | .array_init => { | 520 | .array_init => { |
| 521 | const array_init: Air.ArrayInit = c.air.instData(.array_init, inst); | 521 | const array_init: Air.ArrayInit = c.air.instData(.array_init, inst); |
| 522 | 522 | ||
| 523 | const items = array_init.list.get(&c.air).slice(&c.air); | 523 | const items = array_init.list.get(&c.air).get(&c.air); |
| 524 | const store_offset = try c.extra.alloc(c.gpa, items.len); | 524 | const store_offset = try c.extra.alloc(c.gpa, items.len); |
| 525 | 525 | ||
| 526 | for ( | 526 | for ( |
| ... | @@ -653,7 +653,12 @@ fn valueToExpression(c: *NodeGen, v: Value) !Node.Index { | ... | @@ -653,7 +653,12 @@ fn valueToExpression(c: *NodeGen, v: Value) !Node.Index { |
| 653 | 653 | ||
| 654 | .external_value => { | 654 | .external_value => { |
| 655 | const external = v.toKey(c.ip).external_value; | 655 | const external = v.toKey(c.ip).external_value; |
| 656 | try c.extern_symbols.put(c.gpa, external.key[0].toString().withLen(external.key[0].length(c.ip)), {}); | 656 | const first_key = external.key.at(c.ip, 0); |
| 657 | try c.extern_symbols.put( | ||
| 658 | c.gpa, | ||
| 659 | first_key.toString().withLen(first_key.length(c.ip)), | ||
| 660 | {}, | ||
| 661 | ); | ||
| 657 | return try c.add(.plain_value, .{ .value = v }); | 662 | return try c.add(.plain_value, .{ .value = v }); |
| 658 | }, | 663 | }, |
| 659 | 664 | ||
| ... | @@ -730,7 +735,7 @@ fn codeGenBranch(c: *NodeGen, inst: Air.Inst.Ref, temporary: ?Node.Index) !?Bran | ... | @@ -730,7 +735,7 @@ fn codeGenBranch(c: *NodeGen, inst: Air.Inst.Ref, temporary: ?Node.Index) !?Bran |
| 730 | }); | 735 | }); |
| 731 | 736 | ||
| 732 | const block: Air.IndexList = c.air.instData(.block, i); | 737 | const block: Air.IndexList = c.air.instData(.block, i); |
| 733 | for (block.slice(&c.air)) |item| { | 738 | for (block.get(&c.air)) |item| { |
| 734 | try c.codeGenInst(item); | 739 | try c.codeGenInst(item); |
| 735 | } | 740 | } |
| 736 | 741 | ||
| ... | @@ -781,7 +786,7 @@ fn codeGenBlock(c: *NodeGen, inst: Air.Inst.Index) !void { | ... | @@ -781,7 +786,7 @@ fn codeGenBlock(c: *NodeGen, inst: Air.Inst.Index) !void { |
| 781 | }; | 786 | }; |
| 782 | const block: Air.IndexList = c.air.instData(.block, inst); | 787 | const block: Air.IndexList = c.air.instData(.block, inst); |
| 783 | 788 | ||
| 784 | for (block.slice(&c.air)) |item| { | 789 | for (block.get(&c.air)) |item| { |
| 785 | try c.codeGenInst(item); | 790 | try c.codeGenInst(item); |
| 786 | } | 791 | } |
| 787 | 792 | ||
| ... | @@ -814,7 +819,7 @@ fn codeGenBlockAsExpression(c: *NodeGen, inst: Air.Inst.Index) !Node.Index { | ... | @@ -814,7 +819,7 @@ fn codeGenBlockAsExpression(c: *NodeGen, inst: Air.Inst.Index) !Node.Index { |
| 814 | .block = .{ .index = @intCast(scratch_top) }, | 819 | .block = .{ .index = @intCast(scratch_top) }, |
| 815 | }; | 820 | }; |
| 816 | const block: Air.IndexList = c.air.instData(.block, inst); | 821 | const block: Air.IndexList = c.air.instData(.block, inst); |
| 817 | const instructions = block.slice(&c.air); | 822 | const instructions = block.get(&c.air); |
| 818 | for (instructions[0 .. instructions.len - 1]) |item| { | 823 | for (instructions[0 .. instructions.len - 1]) |item| { |
| 819 | try c.codeGenInst(item); | 824 | try c.codeGenInst(item); |
| 820 | } | 825 | } |
| ... | @@ -885,7 +890,7 @@ fn canLowerToExpression(c: *const NodeGen, inst: Air.Inst.Ref) bool { | ... | @@ -885,7 +890,7 @@ fn canLowerToExpression(c: *const NodeGen, inst: Air.Inst.Ref) bool { |
| 885 | // are lowerable. The break at the end just becomes the result. | 890 | // are lowerable. The break at the end just becomes the result. |
| 886 | .block => { | 891 | .block => { |
| 887 | const block: Air.IndexList = c.air.instData(.block, index); | 892 | const block: Air.IndexList = c.air.instData(.block, index); |
| 888 | const items = block.slice(&c.air); | 893 | const items = block.get(&c.air); |
| 889 | for (items[0 .. items.len - 1]) |item| { | 894 | for (items[0 .. items.len - 1]) |item| { |
| 890 | if (c.air.instFlags(item).uses == .multi) | 895 | if (c.air.instFlags(item).uses == .multi) |
| 891 | return false; | 896 | return false; |
src/manual/generate_manual.zig+11-3| ... | @@ -70,7 +70,7 @@ pub fn main() !void { | ... | @@ -70,7 +70,7 @@ pub fn main() !void { |
| 70 | .contents = contents.items, | 70 | .contents = contents.items, |
| 71 | .navigation = header.data.items, | 71 | .navigation = header.data.items, |
| 72 | .nav_h1 = "Ix Language", | 72 | .nav_h1 = "Ix Language", |
| 73 | .repository = "https://github.com/paperdave/wl", | 73 | .repository = "https://github.com/paperdave/ix", |
| 74 | .style = minified_style, | 74 | .style = minified_style, |
| 75 | }); | 75 | }); |
| 76 | 76 | ||
| ... | @@ -83,7 +83,7 @@ pub fn main() !void { | ... | @@ -83,7 +83,7 @@ pub fn main() !void { |
| 83 | std.debug.lockStdErr(); | 83 | std.debug.lockStdErr(); |
| 84 | std.debug.unlockStdErr(); | 84 | std.debug.unlockStdErr(); |
| 85 | 85 | ||
| 86 | std.process.exit(0); | 86 | std.process.exit(if (header.had_signaled) 1 else 0); |
| 87 | } | 87 | } |
| 88 | 88 | ||
| 89 | const BlockType = enum { | 89 | const BlockType = enum { |
| ... | @@ -190,6 +190,8 @@ const HeaderWriter = struct { | ... | @@ -190,6 +190,8 @@ const HeaderWriter = struct { |
| 190 | 190 | ||
| 191 | has_closed_li: bool = true, | 191 | has_closed_li: bool = true, |
| 192 | 192 | ||
| 193 | had_signaled: bool = false, | ||
| 194 | |||
| 193 | fn add(header: *HeaderWriter, alloc: Allocator, name: []const u8, id: []const u8, level: u8) !void { | 195 | fn add(header: *HeaderWriter, alloc: Allocator, name: []const u8, id: []const u8, level: u8) !void { |
| 194 | const w = header.data.writer(alloc); | 196 | const w = header.data.writer(alloc); |
| 195 | 197 | ||
| ... | @@ -440,6 +442,10 @@ fn processMarkdown( | ... | @@ -440,6 +442,10 @@ fn processMarkdown( |
| 440 | 442 | ||
| 441 | try build.collectOutput(&out, &err, std.math.maxInt(usize)); | 443 | try build.collectOutput(&out, &err, std.math.maxInt(usize)); |
| 442 | const result = try build.wait(); | 444 | const result = try build.wait(); |
| 445 | if (result == .Signal) { | ||
| 446 | std.debug.print("{s}\n", .{err.items}); | ||
| 447 | header.had_signaled = true; | ||
| 448 | } | ||
| 443 | if (result != .Exited or result.Exited != 0) { | 449 | if (result != .Exited or result.Exited != 0) { |
| 444 | try err.writer().print("[Process {s} with {d}]", .{ | 450 | try err.writer().print("[Process {s} with {d}]", .{ |
| 445 | switch (result) { | 451 | switch (result) { |
| ... | @@ -530,7 +536,9 @@ fn processMarkdown( | ... | @@ -530,7 +536,9 @@ fn processMarkdown( |
| 530 | } | 536 | } |
| 531 | return e; | 537 | return e; |
| 532 | }; | 538 | }; |
| 533 | 539 | if (run_result == .Signal) { | |
| 540 | header.had_signaled = true; | ||
| 541 | } | ||
| 534 | if (run_result != .Exited or run_result.Exited != 0) { | 542 | if (run_result != .Exited or run_result.Exited != 0) { |
| 535 | try run_err.writer().print("[Process {s} with {d}]", .{ | 543 | try run_err.writer().print("[Process {s} with {d}]", .{ |
| 536 | switch (run_result) { | 544 | switch (run_result) { |