17 files changed, 86 insertions(+), 77 deletions(-)
build.zig+16-3| ... | @@ -236,9 +236,8 @@ fn createModuleTests(module: *Build.Module, options: Options) *Build.Step.Compil | ... | @@ -236,9 +236,8 @@ fn createModuleTests(module: *Build.Module, options: Options) *Build.Step.Compil |
| 236 | } | 236 | } |
| 237 | 237 | ||
| 238 | pub fn build(b: *Build) !void { | 238 | pub fn build(b: *Build) !void { |
| 239 | b.reference_trace = 32; | 239 | var target = b.standardTargetOptions(.{}); |
| 240 | 240 | var host = b.graph.host; | |
| 241 | const target = b.standardTargetOptions(.{}); | ||
| 242 | 241 | ||
| 243 | // I disagree with how the standard optimize flag works | 242 | // I disagree with how the standard optimize flag works |
| 244 | const optimize_fallback = switch (b.release_mode) { | 243 | const optimize_fallback = switch (b.release_mode) { |
| ... | @@ -272,6 +271,12 @@ pub fn build(b: *Build) !void { | ... | @@ -272,6 +271,12 @@ pub fn build(b: *Build) !void { |
| 272 | "Experiment with the Zig self-hosted backends", | 271 | "Experiment with the Zig self-hosted backends", |
| 273 | ) orelse false; | 272 | ) orelse false; |
| 274 | 273 | ||
| 274 | if (no_llvm) { | ||
| 275 | if (b.user_input_options.getPtr("target") == null) | ||
| 276 | target = mapTargetForSelfHosted(target); | ||
| 277 | host = mapTargetForSelfHosted(host); | ||
| 278 | } | ||
| 279 | |||
| 275 | const have_embedded_quickjs = b.option( | 280 | const have_embedded_quickjs = b.option( |
| 276 | bool, | 281 | bool, |
| 277 | "quickjs", | 282 | "quickjs", |
| ... | @@ -599,6 +604,14 @@ fn crossTarget(cpu_arch: std.Target.Cpu.Arch, os_tag: std.Target.Os.Tag) Build.R | ... | @@ -599,6 +604,14 @@ fn crossTarget(cpu_arch: std.Target.Cpu.Arch, os_tag: std.Target.Os.Tag) Build.R |
| 599 | }; | 604 | }; |
| 600 | } | 605 | } |
| 601 | 606 | ||
| 607 | fn mapTargetForSelfHosted(target: Build.ResolvedTarget) Build.ResolvedTarget { | ||
| 608 | if (target.result.os.tag == .macos and target.result.cpu.arch == .aarch64) { | ||
| 609 | var mut = target; | ||
| 610 | mut.result.cpu = std.Target.Cpu.baseline(.x86_64, target.result.os); | ||
| 611 | } | ||
| 612 | return target; | ||
| 613 | } | ||
| 614 | |||
| 602 | pub const PathOrString = union(enum) { | 615 | pub const PathOrString = union(enum) { |
| 603 | path: LazyPath, | 616 | path: LazyPath, |
| 604 | string: []const u8, | 617 | string: []const u8, |
build.zig.zon+2-2| ... | @@ -7,8 +7,8 @@ | ... | @@ -7,8 +7,8 @@ |
| 7 | .dependencies = .{ | 7 | .dependencies = .{ |
| 8 | // Used to determine unicode properties to tokenize identifiers | 8 | // Used to determine unicode properties to tokenize identifiers |
| 9 | .zg = .{ | 9 | .zg = .{ |
| 10 | .url = "https://codeberg.org/dude_the_builder/zg/archive/c425c9c8511bf92e14b8b612d1d16e774b186f2e.tar.gz", | 10 | .url = "https://codeberg.org/atman/zg/archive/4a002763419a34d61dcbb1f415821b83b9bf8ddc.tar.gz", |
| 11 | .hash = "1220c79009f1e443b015db4de6e5319432538ead2fea10d271f3f35d3ae83c996789", | 11 | .hash = "1220f3e29bc40856bfc06e0ee133f814b0011c76de987d8a6a458c2f34d82708899a", |
| 12 | }, | 12 | }, |
| 13 | // Optional: Used for tracing | 13 | // Optional: Used for tracing |
| 14 | .tracer = .{ | 14 | .tracer = .{ |
doc/language-manual.md+1-2| ... | @@ -1,7 +1,6 @@ | ... | @@ -1,7 +1,6 @@ |
| 1 | # Ix Programming Language | 1 | # Ix Programming Language |
| 2 | 2 | ||
| 3 | Ix (**I**nferable E**x**pression) is a high-level programming language for | 3 | Ix (**I**nferable E**x**pression) is an experimental programming language. |
| 4 | developing web applications and games. | ||
| 5 | 4 | ||
| 6 | Key goals of this project are: | 5 | Key goals of this project are: |
| 7 | 6 |
src/Cli.zig+10-10| ... | @@ -5,6 +5,8 @@ | ... | @@ -5,6 +5,8 @@ |
| 5 | //! | 5 | //! |
| 6 | //! See `fn main` for a basic usage example. Parsing subcommands is done in | 6 | //! See `fn main` for a basic usage example. Parsing subcommands is done in |
| 7 | //! `main.zig`, utilizing a different `Cli` for each option set. | 7 | //! `main.zig`, utilizing a different `Cli` for each option set. |
| 8 | const Cli = @This(); | ||
| 9 | |||
| 8 | options: []const Option, | 10 | options: []const Option, |
| 9 | positionals: Positionals, | 11 | positionals: Positionals, |
| 10 | help: HelpConfig = .{}, | 12 | help: HelpConfig = .{}, |
| ... | @@ -57,14 +59,15 @@ pub const Positionals = union(enum) { | ... | @@ -57,14 +59,15 @@ pub const Positionals = union(enum) { |
| 57 | /// Store the start and count of positionals. Call | 59 | /// Store the start and count of positionals. Call |
| 58 | /// 'parsed.positionals.iterator(args)' with the | 60 | /// 'parsed.positionals.iterator(args)' with the |
| 59 | /// original argument array to read positionals. | 61 | /// original argument array to read positionals. |
| 60 | unlimited, | ||
| 61 | /// Same strategy as .unlimited, with a limit | ||
| 62 | limited: usize, | 62 | limited: usize, |
| 63 | /// Use a bounded array to store positionals, using | 63 | /// Use a bounded array to store positionals, using |
| 64 | /// a stack allocated buffer that can hold enough | 64 | /// a stack allocated buffer that can hold enough |
| 65 | /// '[]const u8's as allowed by the bound. | 65 | /// '[]const u8's as allowed by the bound. |
| 66 | bounded: usize, | 66 | bounded: usize, |
| 67 | 67 | ||
| 68 | /// Shorthand for an unlimited amount of positionals. | ||
| 69 | const unlimited: Positionals = .{ .limited = std.math.maxInt(usize) }; | ||
| 70 | |||
| 68 | pub fn Type(p: Positionals) type { | 71 | pub fn Type(p: Positionals) type { |
| 69 | return switch (p) { | 72 | return switch (p) { |
| 70 | .none => void, | 73 | .none => void, |
| ... | @@ -73,7 +76,6 @@ pub const Positionals = union(enum) { | ... | @@ -73,7 +76,6 @@ pub const Positionals = union(enum) { |
| 73 | 0 => void, | 76 | 0 => void, |
| 74 | else => Multi, | 77 | else => Multi, |
| 75 | }, | 78 | }, |
| 76 | .unlimited => Multi, | ||
| 77 | .bounded => |n| std.BoundedArray([]const u8, n), | 79 | .bounded => |n| std.BoundedArray([]const u8, n), |
| 78 | }; | 80 | }; |
| 79 | } | 81 | } |
| ... | @@ -83,7 +85,6 @@ pub const Positionals = union(enum) { | ... | @@ -83,7 +85,6 @@ pub const Positionals = union(enum) { |
| 83 | .none => 0, | 85 | .none => 0, |
| 84 | .single => 1, | 86 | .single => 1, |
| 85 | inline .limited, .bounded => |limit| limit, | 87 | inline .limited, .bounded => |limit| limit, |
| 86 | .unlimited => std.math.maxInt(usize), | ||
| 87 | }; | 88 | }; |
| 88 | } | 89 | } |
| 89 | 90 | ||
| ... | @@ -188,7 +189,7 @@ pub fn Parsed(p: Cli) type { | ... | @@ -188,7 +189,7 @@ pub fn Parsed(p: Cli) type { |
| 188 | field.* = .{ | 189 | field.* = .{ |
| 189 | .name = fieldName(def.name), | 190 | .name = fieldName(def.name), |
| 190 | .alignment = @alignOf(Wrapped), | 191 | .alignment = @alignOf(Wrapped), |
| 191 | .default_value = &@as(Wrapped, null), | 192 | .default_value_ptr = &@as(Wrapped, null), |
| 192 | .is_comptime = false, | 193 | .is_comptime = false, |
| 193 | .type = Wrapped, | 194 | .type = Wrapped, |
| 194 | }; | 195 | }; |
| ... | @@ -199,10 +200,10 @@ pub fn Parsed(p: Cli) type { | ... | @@ -199,10 +200,10 @@ pub fn Parsed(p: Cli) type { |
| 199 | .name = "positionals", | 200 | .name = "positionals", |
| 200 | .alignment = @alignOf(Pos), | 201 | .alignment = @alignOf(Pos), |
| 201 | .type = Pos, | 202 | .type = Pos, |
| 202 | .default_value = &@as(Pos, switch (p.positionals) { | 203 | .default_value_ptr = &@as(Pos, switch (p.positionals) { |
| 203 | .none => {}, | 204 | .none => {}, |
| 204 | .single => null, | 205 | .single => null, |
| 205 | .limited, .unlimited => .empty, | 206 | .limited => .empty, |
| 206 | .bounded => .{}, | 207 | .bounded => .{}, |
| 207 | }), | 208 | }), |
| 208 | .is_comptime = false, | 209 | .is_comptime = false, |
| ... | @@ -466,7 +467,7 @@ pub fn parseWithErrorWriter( | ... | @@ -466,7 +467,7 @@ pub fn parseWithErrorWriter( |
| 466 | else | 467 | else |
| 467 | null, | 468 | null, |
| 468 | .bounded => out.positionals, // already correct | 469 | .bounded => out.positionals, // already correct |
| 469 | .unlimited, .limited => if (max_positionals > 0) .{ | 470 | .limited => if (max_positionals > 0) .{ |
| 470 | .first = first_positional, | 471 | .first = first_positional, |
| 471 | .len = positionals_counted, | 472 | .len = positionals_counted, |
| 472 | .first_is_after_double_dash = if (double_dash) |dd| | 473 | .first_is_after_double_dash = if (double_dash) |dd| |
| ... | @@ -662,7 +663,7 @@ pub fn main() !void { | ... | @@ -662,7 +663,7 @@ pub fn main() !void { |
| 662 | std.debug.print("--enum: {any}\n", .{parsed.@"enum"}); | 663 | std.debug.print("--enum: {any}\n", .{parsed.@"enum"}); |
| 663 | std.debug.print("positionals({d}):\n", .{parsed.positionals.len}); | 664 | std.debug.print("positionals({d}):\n", .{parsed.positionals.len}); |
| 664 | 665 | ||
| 665 | // if using '.positionals = .unlimited' | 666 | // if using '.positionals = .limited' |
| 666 | // var it = parsed.positionals.iterator(args[1..]); | 667 | // var it = parsed.positionals.iterator(args[1..]); |
| 667 | // while (it.next()) |item| { | 668 | // while (it.next()) |item| { |
| 668 | // std.debug.print(" - {s}\n", .{item}); | 669 | // std.debug.print(" - {s}\n", .{item}); |
| ... | @@ -673,7 +674,6 @@ pub fn main() !void { | ... | @@ -673,7 +674,6 @@ pub fn main() !void { |
| 673 | } | 674 | } |
| 674 | } | 675 | } |
| 675 | 676 | ||
| 676 | const Cli = @This(); | ||
| 677 | const std = @import("std"); | 677 | const std = @import("std"); |
| 678 | const mem = std.mem; | 678 | const mem = std.mem; |
| 679 | const Type = std.builtin.Type; | 679 | const Type = std.builtin.Type; |
src/core/Ast.zig+1-1| ... | @@ -351,7 +351,7 @@ pub const Node = struct { | ... | @@ -351,7 +351,7 @@ pub const Node = struct { |
| 351 | }); | 351 | }); |
| 352 | 352 | ||
| 353 | pub const Data = union { | 353 | pub const Data = union { |
| 354 | none: struct { Unused = .zero, Unused = .zero }, | 354 | none: struct { a: Unused = .zero, b: Unused = .zero }, |
| 355 | function: struct { | 355 | function: struct { |
| 356 | /// A `Fn` | 356 | /// A `Fn` |
| 357 | extra: ExtraIndex, | 357 | extra: ExtraIndex, |
src/core/Comp.zig+3-6| ... | @@ -322,8 +322,9 @@ pub const File = struct { | ... | @@ -322,8 +322,9 @@ pub const File = struct { |
| 322 | return source; | 322 | return source; |
| 323 | } | 323 | } |
| 324 | 324 | ||
| 325 | // Keep track of inode, file size, mtime, hash so we can detect which files | 325 | // Keep track of inode, file size, mtime, hash so the incremental |
| 326 | // have been modified when an incremental update is requested. | 326 | // compiler can detect which files have been modified when an |
| 327 | // incremental update is requested. | ||
| 327 | var f = try std.fs.openFileAbsolute(file.file_path, .{}); | 328 | var f = try std.fs.openFileAbsolute(file.file_path, .{}); |
| 328 | defer f.close(); | 329 | defer f.close(); |
| 329 | 330 | ||
| ... | @@ -338,10 +339,6 @@ pub const File = struct { | ... | @@ -338,10 +339,6 @@ pub const File = struct { |
| 338 | if (amt != stat.size) | 339 | if (amt != stat.size) |
| 339 | return error.UnexpectedEndOfFile; | 340 | return error.UnexpectedEndOfFile; |
| 340 | 341 | ||
| 341 | // Here we do not modify stat fields because this function is the one | ||
| 342 | // used for error reporting. We need to keep the stat fields stale so that | ||
| 343 | // transformFile can know to regenerate Hir. | ||
| 344 | |||
| 345 | const loaded_source: Source = .{ | 342 | const loaded_source: Source = .{ |
| 346 | .code = source, | 343 | .code = source, |
| 347 | .stat = .{ | 344 | .stat = .{ |
src/core/InternPool.zig+8-7| ... | @@ -25,10 +25,10 @@ map: std.AutoArrayHashMapUnmanaged(void, void) = .empty, | ... | @@ -25,10 +25,10 @@ map: std.AutoArrayHashMapUnmanaged(void, void) = .empty, |
| 25 | items: std.MultiArrayList(Item) = .empty, | 25 | items: std.MultiArrayList(Item) = .empty, |
| 26 | extra: Extra = .empty, | 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, all string bytes are |
| 29 | /// string bytes into here. String bytes can be null. It is up to whoever | 29 | /// placed here. String bytes can be null. It is up to whoever is referencing |
| 30 | /// is referencing the data here whether they want to store both index and length, | 30 | /// the data here whether they want to store both index and length, thus |
| 31 | /// thus allowing null bytes, or store only index, and use null-termination. The | 31 | /// allowing null bytes, or store only index, and use null-termination. The |
| 32 | /// `string_bytes` array is agnostic to either usage. | 32 | /// `string_bytes` array is agnostic to either usage. |
| 33 | string_bytes: std.ArrayListUnmanaged(u8) = .empty, | 33 | string_bytes: std.ArrayListUnmanaged(u8) = .empty, |
| 34 | 34 | ||
| ... | @@ -451,6 +451,7 @@ pub const Type = enum(u32) { | ... | @@ -451,6 +451,7 @@ pub const Type = enum(u32) { |
| 451 | }; | 451 | }; |
| 452 | 452 | ||
| 453 | pub const Slice = Extra.Slice(Type); | 453 | pub const Slice = Extra.Slice(Type); |
| 454 | const y = Slice{}; | ||
| 454 | 455 | ||
| 455 | pub fn value(ty: Type) Value { | 456 | pub fn value(ty: Type) Value { |
| 456 | return @enumFromInt(@intFromEnum(ty)); | 457 | return @enumFromInt(@intFromEnum(ty)); |
| ... | @@ -1712,7 +1713,7 @@ pub fn addDependency(ip: *InternPool, gpa: Allocator, depender: AnalysisUnit, de | ... | @@ -1712,7 +1713,7 @@ pub fn addDependency(ip: *InternPool, gpa: Allocator, depender: AnalysisUnit, de |
| 1712 | } | 1713 | } |
| 1713 | 1714 | ||
| 1714 | // Prepend a new dependency. | 1715 | // Prepend a new dependency. |
| 1715 | const new_index: DepEntry.Index, const ptr = if (ip.free_dep_entries.popOrNull()) |new_index| new: { | 1716 | const new_index: DepEntry.Index, const ptr = if (ip.free_dep_entries.pop()) |new_index| new: { |
| 1716 | break :new .{ new_index, &ip.dep_entries.items[@intFromEnum(new_index)] }; | 1717 | break :new .{ new_index, &ip.dep_entries.items[@intFromEnum(new_index)] }; |
| 1717 | } else .{ @enumFromInt(ip.dep_entries.items.len), ip.dep_entries.addOneAssumeCapacity() }; | 1718 | } else .{ @enumFromInt(ip.dep_entries.items.len), ip.dep_entries.addOneAssumeCapacity() }; |
| 1718 | ptr.next = if (gop.found_existing) gop.value_ptr.*.toOptional() else .none; | 1719 | ptr.next = if (gop.found_existing) gop.value_ptr.*.toOptional() else .none; |
| ... | @@ -1751,7 +1752,7 @@ pub fn createDecl( | ... | @@ -1751,7 +1752,7 @@ pub fn createDecl( |
| 1751 | const t = tracer.trace(@src()); | 1752 | const t = tracer.trace(@src()); |
| 1752 | defer t.end(); | 1753 | defer t.end(); |
| 1753 | 1754 | ||
| 1754 | if (ip.decls_free_list.popOrNull()) |index| { | 1755 | if (ip.decls_free_list.pop()) |index| { |
| 1755 | ip.allocated_decls.at(@intFromEnum(index)).* = initialization; | 1756 | ip.allocated_decls.at(@intFromEnum(index)).* = initialization; |
| 1756 | return index; | 1757 | return index; |
| 1757 | } | 1758 | } |
| ... | @@ -1779,7 +1780,7 @@ pub fn createNamespace( | ... | @@ -1779,7 +1780,7 @@ pub fn createNamespace( |
| 1779 | const t = tracer.trace(@src()); | 1780 | const t = tracer.trace(@src()); |
| 1780 | defer t.end(); | 1781 | defer t.end(); |
| 1781 | 1782 | ||
| 1782 | if (ip.namespaces_free_list.popOrNull()) |index| { | 1783 | if (ip.namespaces_free_list.pop()) |index| { |
| 1783 | ip.allocated_namespaces.at(@intFromEnum(index)).* = initialization; | 1784 | ip.allocated_namespaces.at(@intFromEnum(index)).* = initialization; |
| 1784 | return index; | 1785 | return index; |
| 1785 | } | 1786 | } |
src/core/Sema.zig+3-3| ... | @@ -172,7 +172,7 @@ const Frame = struct { | ... | @@ -172,7 +172,7 @@ const Frame = struct { |
| 172 | data: Data, | 172 | data: Data, |
| 173 | 173 | ||
| 174 | const Data = union { | 174 | const Data = union { |
| 175 | pub const none = .{ .undefined = {} }; | 175 | pub const none: Data = .{ .undefined = {} }; |
| 176 | 176 | ||
| 177 | undefined: void, | 177 | undefined: void, |
| 178 | conditional: Conditional, | 178 | conditional: Conditional, |
| ... | @@ -961,7 +961,7 @@ fn stepInner(s: *Sema, comptime tag: Hir.Tag) Error!InstructionKind.fromTag(tag) | ... | @@ -961,7 +961,7 @@ fn stepInner(s: *Sema, comptime tag: Hir.Tag) Error!InstructionKind.fromTag(tag) |
| 961 | const data: Hir.Func = s.frame.currentPayload(.func); | 961 | const data: Hir.Func = s.frame.currentPayload(.func); |
| 962 | const reserve = try s.scratch.reserveMulti( | 962 | const reserve = try s.scratch.reserveMulti( |
| 963 | s.arena(), | 963 | s.arena(), |
| 964 | .{ .params = Type, .captures = Air.Inst.Ref }, | 964 | FunctionReserve.reserve_types, |
| 965 | .{ data.params.len, data.captures.len }, | 965 | .{ data.params.len, data.captures.len }, |
| 966 | ); | 966 | ); |
| 967 | if (data.captures.len > 0) @panic("TODO: captures"); | 967 | if (data.captures.len > 0) @panic("TODO: captures"); |
| ... | @@ -2453,7 +2453,7 @@ fn pushFrame(s: *Sema) !void { | ... | @@ -2453,7 +2453,7 @@ fn pushFrame(s: *Sema) !void { |
| 2453 | } | 2453 | } |
| 2454 | 2454 | ||
| 2455 | fn popFrame(s: *Sema) void { | 2455 | fn popFrame(s: *Sema) void { |
| 2456 | s.frame = s.frame_stack.pop(); | 2456 | s.frame = s.frame_stack.pop() orelse unreachable; |
| 2457 | } | 2457 | } |
| 2458 | 2458 | ||
| 2459 | fn addIndexUntracked(s: *Sema, comptime tag: Air.Inst.Tag, data: tag.Data()) !Air.Inst.Index { | 2459 | fn addIndexUntracked(s: *Sema, comptime tag: Air.Inst.Tag, data: tag.Data()) !Air.Inst.Index { |
src/core/Tokenizer.zig+2-2| ... | @@ -275,8 +275,8 @@ pub const Token = struct { | ... | @@ -275,8 +275,8 @@ pub const Token = struct { |
| 275 | } | 275 | } |
| 276 | }; | 276 | }; |
| 277 | 277 | ||
| 278 | /// Instead of storing the length of a token, we can recompute this | 278 | /// Instead of storing the length of a token, it's recomputed on demand by |
| 279 | /// information on demand, as it is not often needed. | 279 | /// tokenizing the text. This trade-off was done to preserve memory. |
| 280 | /// | 280 | /// |
| 281 | /// When computing the length of something that can be known without | 281 | /// When computing the length of something that can be known without |
| 282 | /// the source code, use token.tag.staticLen() instead. | 282 | /// the source code, use token.tag.staticLen() instead. |
src/core/Transform.zig+12-13| ... | @@ -369,18 +369,18 @@ const BuiltIn = struct { | ... | @@ -369,18 +369,18 @@ const BuiltIn = struct { |
| 369 | }; | 369 | }; |
| 370 | 370 | ||
| 371 | const built_in_ids = std.StaticStringMap(BuiltIn).initComptime(.{ | 371 | const built_in_ids = std.StaticStringMap(BuiltIn).initComptime(.{ |
| 372 | .{ "void", .{ .value = .void, .type = .void } }, | 372 | .{ "void", BuiltIn{ .value = .void, .type = .void } }, |
| 373 | .{ "true", .{ .value = .bool_true, .type = .bool_type } }, | 373 | .{ "true", BuiltIn{ .value = .bool_true, .type = .bool_type } }, |
| 374 | .{ "false", .{ .value = .bool_false, .type = .bool_type } }, | 374 | .{ "false", BuiltIn{ .value = .bool_false, .type = .bool_type } }, |
| 375 | .{ "int", .{ .value = .int32_type, .type = .type_type } }, | 375 | .{ "int", BuiltIn{ .value = .int32_type, .type = .type_type } }, |
| 376 | .{ "float", .{ .value = .float_type, .type = .type_type } }, | 376 | .{ "float", BuiltIn{ .value = .float_type, .type = .type_type } }, |
| 377 | .{ "string", .{ .value = .string_type, .type = .type_type } }, | 377 | .{ "string", BuiltIn{ .value = .string_type, .type = .type_type } }, |
| 378 | .{ "opaque", .{ .value = .opaque_type, .type = .type_type } }, | 378 | .{ "opaque", BuiltIn{ .value = .opaque_type, .type = .type_type } }, |
| 379 | // .{ "bigint", .{ .value = .bigint_type, .type = .type_type } }, | 379 | // .{ "bigint", BuiltIn{ .value = .bigint_type, .type = .type_type } }, |
| 380 | .{ "bool", .{ .value = .bool_type, .type = .type_type } }, | 380 | .{ "bool", BuiltIn{ .value = .bool_type, .type = .type_type } }, |
| 381 | .{ "never", .{ .value = .never_type, .type = .type_type } }, | 381 | .{ "never", BuiltIn{ .value = .never_type, .type = .type_type } }, |
| 382 | .{ "type", .{ .value = .type_type, .type = .type_type } }, | 382 | .{ "type", BuiltIn{ .value = .type_type, .type = .type_type } }, |
| 383 | // .{ "std", .{ .value = .standard_library, .type = ... } }, | 383 | // .{ "std", BuiltIn{ .value = .standard_library, .type = ... } }, |
| 384 | }); | 384 | }); |
| 385 | 385 | ||
| 386 | fn transformModule(t: *Transform, module_node: NodeIndex) Allocator.Error!Inst.Index { | 386 | fn transformModule(t: *Transform, module_node: NodeIndex) Allocator.Error!Inst.Index { |
| ... | @@ -412,7 +412,6 @@ fn transformModule(t: *Transform, module_node: NodeIndex) Allocator.Error!Inst.I | ... | @@ -412,7 +412,6 @@ fn transformModule(t: *Transform, module_node: NodeIndex) Allocator.Error!Inst.I |
| 412 | defer t.gpa.free(decls); | 412 | defer t.gpa.free(decls); |
| 413 | 413 | ||
| 414 | { | 414 | { |
| 415 | // `transformDecl` is not allowed to mutate symbols as we rely on the stable value. | ||
| 416 | s.symbols.lockPointers(); | 415 | s.symbols.lockPointers(); |
| 417 | defer s.symbols.unlockPointers(); | 416 | defer s.symbols.unlockPointers(); |
| 418 | 417 |
src/core/array.zig+14-16| ... | @@ -90,7 +90,7 @@ pub const StoreKind = enum { | ... | @@ -90,7 +90,7 @@ pub const StoreKind = enum { |
| 90 | 90 | ||
| 91 | pub fn ResolvedStore(kind: StoreKind, Owner: type) type { | 91 | pub fn ResolvedStore(kind: StoreKind, Owner: type) type { |
| 92 | const ptr = @typeInfo(Owner).pointer; | 92 | const ptr = @typeInfo(Owner).pointer; |
| 93 | assert(ptr.size == .One); | 93 | assert(ptr.size == .one); |
| 94 | const mutability = brk: for (@typeInfo(ptr.child).@"struct".fields) |field| { | 94 | const mutability = brk: for (@typeInfo(ptr.child).@"struct".fields) |field| { |
| 95 | if (std.mem.eql(u8, field.name, "extra")) { | 95 | if (std.mem.eql(u8, field.name, "extra")) { |
| 96 | break :brk field.type.mutability; | 96 | break :brk field.type.mutability; |
| ... | @@ -100,7 +100,7 @@ pub const StoreKind = enum { | ... | @@ -100,7 +100,7 @@ pub const StoreKind = enum { |
| 100 | } | 100 | } |
| 101 | 101 | ||
| 102 | pub fn ResolvedStorePtr(kind: StoreKind, Owner: type) type { | 102 | pub fn ResolvedStorePtr(kind: StoreKind, Owner: type) type { |
| 103 | return kind.ItemPointer(Owner, .One, kind.ResolvedStore(Owner)); | 103 | return kind.ItemPointer(Owner, .one, kind.ResolvedStore(Owner)); |
| 104 | } | 104 | } |
| 105 | 105 | ||
| 106 | pub fn ItemPointer( | 106 | pub fn ItemPointer( |
| ... | @@ -110,18 +110,16 @@ pub const StoreKind = enum { | ... | @@ -110,18 +110,16 @@ pub const StoreKind = enum { |
| 110 | child: type, | 110 | child: type, |
| 111 | ) type { | 111 | ) type { |
| 112 | const ptr = @typeInfo(Owner).pointer; | 112 | const ptr = @typeInfo(Owner).pointer; |
| 113 | return @Type(.{ | 113 | return @Type(.{ .pointer = .{ |
| 114 | .pointer = .{ | 114 | .size = size, |
| 115 | .size = size, | 115 | .is_const = ptr.is_const or ResolvedStore(kind, Owner).mutability == .@"const", |
| 116 | .is_const = ptr.is_const or ResolvedStore(kind, Owner).mutability == .@"const", | 116 | .is_volatile = false, |
| 117 | .is_volatile = false, | 117 | .is_allowzero = false, |
| 118 | .is_allowzero = false, | 118 | .alignment = @alignOf(child), |
| 119 | .alignment = @alignOf(child), | 119 | .address_space = .generic, |
| 120 | .address_space = .generic, | 120 | .child = child, |
| 121 | .child = child, | 121 | .sentinel_ptr = null, |
| 122 | .sentinel = null, | 122 | } }); |
| 123 | }, | ||
| 124 | }); | ||
| 125 | } | 123 | } |
| 126 | }; | 124 | }; |
| 127 | 125 | ||
| ... | @@ -264,7 +262,7 @@ pub fn Store(set_kind: StoreKind, set_mutability: Mutability) type { | ... | @@ -264,7 +262,7 @@ pub fn Store(set_kind: StoreKind, set_mutability: Mutability) type { |
| 264 | .len = 0, | 262 | .len = 0, |
| 265 | }; | 263 | }; |
| 266 | 264 | ||
| 267 | pub fn get(slice: @This(), owner: anytype) kind.ItemPointer(@TypeOf(owner), .Slice, T) { | 265 | 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]); | 266 | return @ptrCast(kind.resolveStore(owner).list.items[slice.start..][0..slice.len]); |
| 269 | } | 267 | } |
| 270 | 268 | ||
| ... | @@ -448,7 +446,7 @@ pub fn Store(set_kind: StoreKind, set_mutability: Mutability) type { | ... | @@ -448,7 +446,7 @@ pub fn Store(set_kind: StoreKind, set_mutability: Mutability) type { |
| 448 | 446 | ||
| 449 | pub fn appendSlice(store: *Self, gpa: Allocator, data: anytype) !Slice(std.meta.Child(@TypeOf(data))) { | 447 | pub fn appendSlice(store: *Self, gpa: Allocator, data: anytype) !Slice(std.meta.Child(@TypeOf(data))) { |
| 450 | const idx = store.list.items.len; | 448 | const idx = store.list.items.len; |
| 451 | comptime assert(@typeInfo(@TypeOf(data)).pointer.size == .Slice); | 449 | comptime assert(@typeInfo(@TypeOf(data)).pointer.size == .slice); |
| 452 | comptime assert(@typeInfo(@TypeOf(data)).pointer.alignment == @alignOf(u32)); | 450 | comptime assert(@typeInfo(@TypeOf(data)).pointer.alignment == @alignOf(u32)); |
| 453 | comptime assert(@sizeOf(@TypeOf(data[0])) == @sizeOf(u32)); | 451 | comptime assert(@sizeOf(@TypeOf(data[0])) == @sizeOf(u32)); |
| 454 | comptime assert(@alignOf(@TypeOf(data[0])) == @alignOf(u32)); | 452 | comptime assert(@alignOf(@TypeOf(data[0])) == @alignOf(u32)); |
src/core/js/Link.zig+4-4| ... | @@ -677,10 +677,10 @@ fn writeString(decoded: []const u8, writer: Writer) !void { | ... | @@ -677,10 +677,10 @@ fn writeString(decoded: []const u8, writer: Writer) !void { |
| 677 | text = text[width..]; | 677 | text = text[width..]; |
| 678 | 678 | ||
| 679 | switch (c) { | 679 | switch (c) { |
| 680 | // Special-case the bell character since it may cause dumping this file to | 680 | // Special-case the bell character since it may cause dumping this |
| 681 | // the terminal to make a sound, which is undesirable. Note that we can't | 681 | // file to the terminal to make a sound, which is undesirable. Note |
| 682 | // use an octal literal to print this shorter since octal literals are not | 682 | // that an octal literal to print this shorter since octal literals |
| 683 | // allowed in strict mode (or in template strings). | 683 | // are not allowed in strict mode (or in template strings). |
| 684 | 0x07 => { | 684 | 0x07 => { |
| 685 | try writer.writeAll("\\x07"); | 685 | try writer.writeAll("\\x07"); |
| 686 | }, | 686 | }, |
src/core/js/NodeGen.zig+1-1| ... | @@ -456,7 +456,7 @@ fn codeGenInst(c: *NodeGen, inst: Air.Inst.Index) Error!void { | ... | @@ -456,7 +456,7 @@ fn codeGenInst(c: *NodeGen, inst: Air.Inst.Index) Error!void { |
| 456 | // of a block. | 456 | // of a block. |
| 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, so this prevents that invalid codegen. |
| 460 | const main_insts = c.air.instData(.block, .main_block).get(&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; |
src/core/stack.zig+4-2| ... | @@ -104,6 +104,8 @@ pub fn Stack(comptime Base: type) type { | ... | @@ -104,6 +104,8 @@ pub fn Stack(comptime Base: type) type { |
| 104 | starts: [fields.len]u32, | 104 | starts: [fields.len]u32, |
| 105 | lengths: [fields.len]u32, | 105 | lengths: [fields.len]u32, |
| 106 | 106 | ||
| 107 | pub const reserve_types = types; | ||
| 108 | |||
| 107 | fn Type(comptime field: FieldEnum) type { | 109 | fn Type(comptime field: FieldEnum) type { |
| 108 | return @field(types, @tagName(field)); | 110 | return @field(types, @tagName(field)); |
| 109 | } | 111 | } |
| ... | @@ -156,10 +158,10 @@ pub fn Stack(comptime Base: type) type { | ... | @@ -156,10 +158,10 @@ pub fn Stack(comptime Base: type) type { |
| 156 | stack: *Self, | 158 | stack: *Self, |
| 157 | allocator: Allocator, | 159 | allocator: Allocator, |
| 158 | comptime types: anytype, | 160 | comptime types: anytype, |
| 159 | lengths: [std.meta.fields(@TypeOf(types)).len]u32, | 161 | lengths: [@typeInfo(@TypeOf(types)).@"struct".fields.len]u32, |
| 160 | ) !ReserveMulti(types) { | 162 | ) !ReserveMulti(types) { |
| 161 | var all_lengths: usize = 0; | 163 | var all_lengths: usize = 0; |
| 162 | var starts: [std.meta.fields(@TypeOf(types)).len]u32 = undefined; | 164 | var starts: [@typeInfo(@TypeOf(types)).@"struct".fields.len]u32 = undefined; |
| 163 | const start = stack.list.items.len; | 165 | const start = stack.list.items.len; |
| 164 | inline for (lengths, &starts) |len, *slice_start| { | 166 | inline for (lengths, &starts) |len, *slice_start| { |
| 165 | slice_start.* = @intCast(start + all_lengths); | 167 | slice_start.* = @intCast(start + all_lengths); |
src/core/unicode_props.zig+3-3| ... | @@ -6,7 +6,7 @@ const tracer = @import("tracer"); | ... | @@ -6,7 +6,7 @@ const tracer = @import("tracer"); |
| 6 | var props: ?PropsData = undefined; | 6 | var props: ?PropsData = undefined; |
| 7 | var props_memory: []u8 = undefined; | 7 | var props_memory: []u8 = undefined; |
| 8 | 8 | ||
| 9 | const raw_allocator = if (@import("builtin").target.isWasm()) | 9 | const raw_allocator = if (@import("builtin").target.cpu.arch.isWasm()) |
| 10 | std.heap.wasm_allocator | 10 | std.heap.wasm_allocator |
| 11 | else | 11 | else |
| 12 | std.heap.page_allocator; | 12 | std.heap.page_allocator; |
| ... | @@ -17,9 +17,9 @@ pub fn init() !void { | ... | @@ -17,9 +17,9 @@ pub fn init() !void { |
| 17 | const trace = tracer.trace(@src()); | 17 | const trace = tracer.trace(@src()); |
| 18 | defer trace.end(); | 18 | defer trace.end(); |
| 19 | 19 | ||
| 20 | // We know exactly how much this uses, so let's preallocate these pages and use a FBA. | 20 | // The uncompressed unicode data has a fixed size allocated on startup. |
| 21 | // In practice, it is never freed. | ||
| 21 | const allocation_size = 8704 + 34560 + 8704 + 17664 + 8704 + 25856; | 22 | const allocation_size = 8704 + 34560 + 8704 + 17664 + 8704 + 25856; |
| 22 | |||
| 23 | if (allocation_size == 0) { | 23 | if (allocation_size == 0) { |
| 24 | var logging_alloc = std.heap.loggingAllocator(std.heap.page_allocator); | 24 | var logging_alloc = std.heap.loggingAllocator(std.heap.page_allocator); |
| 25 | props = try PropsData.init(logging_alloc.allocator()); | 25 | props = try PropsData.init(logging_alloc.allocator()); |
src/deps/quickjs/build.zig+1-1| ... | @@ -163,7 +163,7 @@ fn runQjsc(b: *Build, qjsc: *Build.Step.Compile, in: Build.LazyPath) Build.LazyP | ... | @@ -163,7 +163,7 @@ fn runQjsc(b: *Build, qjsc: *Build.Step.Compile, in: Build.LazyPath) Build.LazyP |
| 163 | return out; | 163 | return out; |
| 164 | } | 164 | } |
| 165 | 165 | ||
| 166 | /// Zig doesnt include winpthreads, so we build it from source. This helper | 166 | /// Zig doesnt include winpthreads, so it's built from source. This helper |
| 167 | /// decides if it is needed, and provides a no-op `configure` function if it is | 167 | /// decides if it is needed, and provides a no-op `configure` function if it is |
| 168 | /// not actually needed. Call .configure on any object files you need. | 168 | /// not actually needed. Call .configure on any object files you need. |
| 169 | const WinPthreads = struct { | 169 | const WinPthreads = struct { |
src/main.zig+1-1| ... | @@ -41,7 +41,7 @@ const top_level_commands: []const Command.ListItem = &.{ | ... | @@ -41,7 +41,7 @@ const top_level_commands: []const Command.ListItem = &.{ |
| 41 | .name = "run", | 41 | .name = "run", |
| 42 | .description = "Create executable and run with QuickJS", | 42 | .description = "Create executable and run with QuickJS", |
| 43 | .cli = .{ | 43 | .cli = .{ |
| 44 | .options = general_compiler_options ++ .{ | 44 | .options = general_compiler_options ++ [_]Cli.Option{ |
| 45 | .{ .name = "--dump-code", .desc = "Dump compiled JavaScript to standard out" }, | 45 | .{ .name = "--dump-code", .desc = "Dump compiled JavaScript to standard out" }, |
| 46 | }, | 46 | }, |
| 47 | .positionals = .single, | 47 | .positionals = .single, |