aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build.zig1
-rw-r--r--doc/langref.html.in4
-rw-r--r--lib/std/build.zig11
-rw-r--r--lib/std/debug.zig5
-rw-r--r--lib/std/os.zig152
-rw-r--r--lib/std/special/compiler_rt.zig9
-rw-r--r--lib/std/special/compiler_rt/aulldiv.zig121
-rw-r--r--lib/std/special/compiler_rt/aullrem.zig123
-rw-r--r--lib/std/special/compiler_rt/extendXfYf2_test.zig6
-rw-r--r--lib/std/special/doc/index.html85
-rw-r--r--lib/std/special/doc/main.js382
-rw-r--r--lib/std/special/docs/index.html356
-rw-r--r--lib/std/special/docs/main.js1194
-rw-r--r--lib/std/special/start_windows_tls.zig12
-rw-r--r--lib/std/std.zig120
-rw-r--r--src/all_types.hpp47
-rw-r--r--src/analyze.cpp47
-rw-r--r--src/ast_render.cpp3
-rw-r--r--src/buffer.hpp6
-rw-r--r--src/codegen.cpp9
-rw-r--r--src/dump_analysis.cpp393
-rw-r--r--src/ir.cpp54
-rw-r--r--src/main.cpp4
-rw-r--r--src/parser.cpp49
-rw-r--r--src/tokenizer.cpp53
-rw-r--r--src/tokenizer.hpp1
26 files changed, 2459 insertions, 788 deletions
diff --git a/build.zig b/build.zig
index 390f1594f8..ca78bdf197 100644
--- a/build.zig
+++ b/build.zig
@@ -373,6 +373,7 @@ fn addLibUserlandStep(b: *Builder, mode: builtin.Mode) void {
artifact.bundle_compiler_rt = true;
artifact.setTarget(builtin.arch, builtin.os, builtin.abi);
artifact.setBuildMode(mode);
+ artifact.force_pic = true;
if (mode != .Debug) {
artifact.strip = true;
}
diff --git a/doc/langref.html.in b/doc/langref.html.in
index 844314c144..a30670b0c7 100644
--- a/doc/langref.html.in
+++ b/doc/langref.html.in
@@ -10062,7 +10062,7 @@ fn readU32Be() u32 {}
<li>Ascii control characters, except for U+000a (LF): U+0000 - U+0009, U+000b - U+0001f, U+007f. (Note that Windows line endings (CRLF) are not allowed, and hard tabs are not allowed.)</li>
<li>Non-Ascii Unicode line endings: U+0085 (NEL), U+2028 (LS), U+2029 (PS).</li>
</ul>
- <p>The codepoint U+000a (LF) (which is encoded as the single-byte value 0x0a) is the line terminator character. This character always terminates a line of zig source code (except possbly the last line of the file).</p>
+ <p>The codepoint U+000a (LF) (which is encoded as the single-byte value 0x0a) is the line terminator character. This character always terminates a line of zig source code (except possibly the last line of the file).</p>
<p>For some discussion on the rationale behind these design decisions, see <a href="https://github.com/ziglang/zig/issues/663">issue #663</a></p>
{#header_close#}
@@ -10097,7 +10097,7 @@ TopLevelComptime &lt;- KEYWORD_comptime BlockExpr
TopLevelDecl
&lt;- (KEYWORD_export / KEYWORD_extern STRINGLITERAL? / KEYWORD_inline)? FnProto (SEMICOLON / Block)
/ (KEYWORD_export / KEYWORD_extern STRINGLITERAL?)? KEYWORD_threadlocal? VarDecl
- / KEYWORD_use Expr SEMICOLON
+ / KEYWORD_usingnamespace Expr SEMICOLON
FnProto &lt;- FnCC? KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? LinkSection? EXCLAMATIONMARK? (KEYWORD_var / TypeExpr)
diff --git a/lib/std/build.zig b/lib/std/build.zig
index c640f6e8f3..cc062f3af8 100644
--- a/lib/std/build.zig
+++ b/lib/std/build.zig
@@ -1488,6 +1488,9 @@ pub const LibExeObjStep = struct {
dynamic_linker: ?[]const u8 = null,
+ /// Position Independent Code
+ force_pic: ?bool = null,
+
const LinkObject = union(enum) {
StaticPath: []const u8,
OtherStep: *LibExeObjStep,
@@ -2314,6 +2317,14 @@ pub const LibExeObjStep = struct {
try zig_args.append(builder.pathFromRoot(dir));
}
+ if (self.force_pic) |pic| {
+ if (pic) {
+ try zig_args.append("-fPIC");
+ } else {
+ try zig_args.append("-fno-PIC");
+ }
+ }
+
if (self.kind == Kind.Test) {
try builder.spawnChild(zig_args.toSliceConst());
} else {
diff --git a/lib/std/debug.zig b/lib/std/debug.zig
index 25868d67a1..a6bc0fedf3 100644
--- a/lib/std/debug.zig
+++ b/lib/std/debug.zig
@@ -2439,3 +2439,8 @@ pub fn dumpStackPointerAddr(prefix: []const u8) void {
);
std.debug.warn("{} sp = 0x{x}\n", prefix, sp);
}
+
+// Reference everything so it gets tested.
+test "" {
+ _ = leb;
+}
diff --git a/lib/std/os.zig b/lib/std/os.zig
index c520e1d635..c05c911148 100644
--- a/lib/std/os.zig
+++ b/lib/std/os.zig
@@ -183,7 +183,7 @@ pub fn abort() noreturn {
exit(127);
}
-pub const RaiseError = error{Unexpected};
+pub const RaiseError = UnexpectedError;
pub fn raise(sig: u8) RaiseError!void {
if (builtin.link_libc) {
@@ -215,10 +215,7 @@ pub fn raise(sig: u8) RaiseError!void {
@compileError("std.os.raise unimplemented for this target");
}
-pub const KillError = error{
- PermissionDenied,
- Unexpected,
-};
+pub const KillError = error{PermissionDenied} || UnexpectedError;
pub fn kill(pid: pid_t, sig: u8) KillError!void {
switch (errno(system.kill(pid, sig))) {
@@ -266,9 +263,7 @@ pub const ReadError = error{
/// This error occurs when no global event loop is configured,
/// and reading from the file descriptor would block.
WouldBlock,
-
- Unexpected,
-};
+} || UnexpectedError;
/// Returns the number of bytes that were read, which can be less than
/// buf.len. If 0 bytes were read, that means EOF.
@@ -385,8 +380,7 @@ pub const WriteError = error{
BrokenPipe,
SystemResources,
OperationAborted,
- Unexpected,
-};
+} || UnexpectedError;
/// Write to a file descriptor. Keeps trying if it gets interrupted.
/// This function is for blocking file descriptors only.
@@ -548,8 +542,7 @@ pub const OpenError = error{
NotDir,
PathAlreadyExists,
DeviceBusy,
- Unexpected,
-};
+} || UnexpectedError;
/// Open and possibly create a file. Keeps trying if it gets interrupted.
/// See also `openC`.
@@ -748,9 +741,7 @@ pub const ExecveError = error{
ProcessFdQuotaExceeded,
SystemFdQuotaExceeded,
NameTooLong,
-
- Unexpected,
-};
+} || UnexpectedError;
fn execveErrnoToErr(err: usize) ExecveError {
assert(err > 0);
@@ -808,8 +799,7 @@ pub fn getenvC(key: [*]const u8) ?[]const u8 {
pub const GetCwdError = error{
NameTooLong,
CurrentWorkingDirectoryUnlinked,
- Unexpected,
-};
+} || UnexpectedError;
/// The result is a slice of out_buffer, indexed from 0.
pub fn getcwd(out_buffer: []u8) GetCwdError![]u8 {
@@ -846,8 +836,7 @@ pub const SymLinkError = error{
NameTooLong,
InvalidUtf8,
BadPathName,
- Unexpected,
-};
+} || UnexpectedError;
/// Creates a symbolic link named `sym_link_path` which contains the string `target_path`.
/// A symbolic link (also known as a soft link) may point to an existing file or to a nonexistent
@@ -932,7 +921,6 @@ pub const UnlinkError = error{
NotDir,
SystemResources,
ReadOnlyFileSystem,
- Unexpected,
/// On Windows, file paths must be valid Unicode.
InvalidUtf8,
@@ -940,7 +928,7 @@ pub const UnlinkError = error{
/// On Windows, file paths cannot contain these characters:
/// '/', '*', '?', '"', '<', '>', '|'
BadPathName,
-};
+} || UnexpectedError;
/// Delete a name and possibly the file it refers to.
/// See also `unlinkC`.
@@ -996,8 +984,7 @@ const RenameError = error{
RenameAcrossMountPoints,
InvalidUtf8,
BadPathName,
- Unexpected,
-};
+} || UnexpectedError;
/// Change the name or location of a file.
pub fn rename(old_path: []const u8, new_path: []const u8) RenameError!void {
@@ -1064,8 +1051,7 @@ pub const MakeDirError = error{
ReadOnlyFileSystem,
InvalidUtf8,
BadPathName,
- Unexpected,
-};
+} || UnexpectedError;
/// Create a directory.
/// `mode` is ignored on Windows.
@@ -1116,8 +1102,7 @@ pub const DeleteDirError = error{
ReadOnlyFileSystem,
InvalidUtf8,
BadPathName,
- Unexpected,
-};
+} || UnexpectedError;
/// Deletes an empty directory.
pub fn rmdir(dir_path: []const u8) DeleteDirError!void {
@@ -1163,8 +1148,7 @@ pub const ChangeCurDirError = error{
FileNotFound,
SystemResources,
NotDir,
- Unexpected,
-};
+} || UnexpectedError;
/// Changes the current working directory of the calling process.
/// `dir_path` is recommended to be a UTF-8 encoded string.
@@ -1206,8 +1190,7 @@ pub const ReadLinkError = error{
FileNotFound,
SystemResources,
NotDir,
- Unexpected,
-};
+} || UnexpectedError;
/// Read value of a symbolic link.
/// The return value is a slice of `out_buffer` from index 0.
@@ -1247,8 +1230,7 @@ pub const SetIdError = error{
ResourceLimitReached,
InvalidUserId,
PermissionDenied,
- Unexpected,
-};
+} || UnexpectedError;
pub fn setuid(uid: u32) SetIdError!void {
switch (errno(system.setuid(uid))) {
@@ -1357,9 +1339,7 @@ pub const SocketError = error{
/// The protocol type or the specified protocol is not supported within this domain.
ProtocolNotSupported,
-
- Unexpected,
-};
+} || UnexpectedError;
pub fn socket(domain: u32, socket_type: u32, protocol: u32) SocketError!i32 {
const rc = system.socket(domain, socket_type, protocol);
@@ -1409,9 +1389,7 @@ pub const BindError = error{
/// The socket inode would reside on a read-only filesystem.
ReadOnlyFileSystem,
-
- Unexpected,
-};
+} || UnexpectedError;
/// addr is `*const T` where T is one of the sockaddr
pub fn bind(fd: i32, addr: *const sockaddr) BindError!void {
@@ -1448,9 +1426,7 @@ const ListenError = error{
/// The socket is not of a type that supports the listen() operation.
OperationNotSupported,
-
- Unexpected,
-};
+} || UnexpectedError;
pub fn listen(sockfd: i32, backlog: u32) ListenError!void {
const rc = system.listen(sockfd, backlog);
@@ -1487,9 +1463,7 @@ pub const AcceptError = error{
/// Firewall rules forbid connection.
BlockedByFirewall,
-
- Unexpected,
-};
+} || UnexpectedError;
/// Accept a connection on a socket. `fd` must be opened in blocking mode.
/// See also `accept4_async`.
@@ -1559,9 +1533,7 @@ pub const EpollCreateError = error{
/// There was insufficient memory to create the kernel object.
SystemResources,
-
- Unexpected,
-};
+} || UnexpectedError;
pub fn epoll_create1(flags: u32) EpollCreateError!i32 {
const rc = system.epoll_create1(flags);
@@ -1600,9 +1572,7 @@ pub const EpollCtlError = error{
/// The target file fd does not support epoll. This error can occur if fd refers to,
/// for example, a regular file or a directory.
FileDescriptorIncompatibleWithEpoll,
-
- Unexpected,
-};
+} || UnexpectedError;
pub fn epoll_ctl(epfd: i32, op: u32, fd: i32, event: ?*epoll_event) EpollCtlError!void {
const rc = system.epoll_ctl(epfd, op, fd, event);
@@ -1643,8 +1613,7 @@ pub const EventFdError = error{
SystemResources,
ProcessFdQuotaExceeded,
SystemFdQuotaExceeded,
- Unexpected,
-};
+} || UnexpectedError;
pub fn eventfd(initval: u32, flags: u32) EventFdError!i32 {
const rc = system.eventfd(initval, flags);
@@ -1663,9 +1632,7 @@ pub fn eventfd(initval: u32, flags: u32) EventFdError!i32 {
pub const GetSockNameError = error{
/// Insufficient resources were available in the system to perform the operation.
SystemResources,
-
- Unexpected,
-};
+} || UnexpectedError;
pub fn getsockname(sockfd: i32) GetSockNameError!sockaddr {
var addr: sockaddr = undefined;
@@ -1714,9 +1681,7 @@ pub const ConnectError = error{
/// Timeout while attempting connection. The server may be too busy to accept new connections. Note
/// that for IP sockets the timeout may be very long when syncookies are enabled on the server.
ConnectionTimedOut,
-
- Unexpected,
-};
+} || UnexpectedError;
/// Initiate a connection on a socket.
/// This is for blocking file descriptors only.
@@ -1747,7 +1712,7 @@ pub fn connect(sockfd: i32, sock_addr: *sockaddr, len: socklen_t) ConnectError!v
}
}
-/// Same as `connect` except it is for blocking socket file descriptors.
+/// Same as `connect` except it is for non-blocking socket file descriptors.
/// It expects to receive EINPROGRESS`.
pub fn connect_async(sockfd: i32, sock_addr: *sockaddr, len: socklen_t) ConnectError!void {
while (true) {
@@ -1824,10 +1789,7 @@ pub fn waitpid(pid: i32, flags: u32) u32 {
}
}
-pub const FStatError = error{
- SystemResources,
- Unexpected,
-};
+pub const FStatError = error{SystemResources} || UnexpectedError;
pub fn fstat(fd: fd_t) FStatError!Stat {
var stat: Stat = undefined;
@@ -1856,9 +1818,7 @@ pub const KQueueError = error{
/// The system-wide limit on the total number of open files has been reached.
SystemFdQuotaExceeded,
-
- Unexpected,
-};
+} || UnexpectedError;
pub fn kqueue() KQueueError!i32 {
const rc = system.kqueue();
@@ -1922,8 +1882,7 @@ pub const INotifyInitError = error{
ProcessFdQuotaExceeded,
SystemFdQuotaExceeded,
SystemResources,
- Unexpected,
-};
+} || UnexpectedError;
/// initialize an inotify instance
pub fn inotify_init1(flags: u32) INotifyInitError!i32 {
@@ -1944,8 +1903,7 @@ pub const INotifyAddWatchError = error{
FileNotFound,
SystemResources,
UserResourceLimitReached,
- Unexpected,
-};
+} || UnexpectedError;
/// add a watch to an initialized inotify instance
pub fn inotify_add_watch(inotify_fd: i32, pathname: []const u8, mask: u32) INotifyAddWatchError!i32 {
@@ -1992,8 +1950,7 @@ pub const MProtectError = error{
/// dle of a region currently protected as PROT_READ|PROT_WRITE would result in three map‐
/// pings: two read/write mappings at each end and a read-only mapping in the middle.)
OutOfMemory,
- Unexpected,
-};
+} || UnexpectedError;
/// `memory.len` must be page-aligned.
pub fn mprotect(memory: []align(mem.page_size) u8, protection: u32) MProtectError!void {
@@ -2007,10 +1964,7 @@ pub fn mprotect(memory: []align(mem.page_size) u8, protection: u32) MProtectErro
}
}
-pub const ForkError = error{
- SystemResources,
- Unexpected,
-};
+pub const ForkError = error{SystemResources} || UnexpectedError;
pub fn fork() ForkError!pid_t {
const rc = system.fork();
@@ -2037,8 +1991,7 @@ pub const MMapError = error{
PermissionDenied,
LockedMemoryLimitExceeded,
OutOfMemory,
- Unexpected,
-};
+} || UnexpectedError;
/// Map files or devices into memory.
/// Use of a mapped region can result in these signals:
@@ -2101,9 +2054,7 @@ pub const AccessError = error{
/// On Windows, file paths must be valid Unicode.
InvalidUtf8,
-
- Unexpected,
-};
+} || UnexpectedError;
/// check user's permissions for a file
/// TODO currently this assumes `mode` is `F_OK` on Windows.
@@ -2161,8 +2112,7 @@ pub fn accessW(path: [*]const u16, mode: u32) windows.GetFileAttributesError!voi
pub const PipeError = error{
SystemFdQuotaExceeded,
ProcessFdQuotaExceeded,
- Unexpected,
-};
+} || UnexpectedError;
/// Creates a unidirectional data channel that can be used for interprocess communication.
pub fn pipe() PipeError![2]fd_t {
@@ -2193,8 +2143,7 @@ pub const SysCtlError = error{
PermissionDenied,
SystemResources,
NameTooLong,
- Unexpected,
-};
+} || UnexpectedError;
pub fn sysctl(
name: []const c_int,
@@ -2237,10 +2186,7 @@ pub fn gettimeofday(tv: ?*timeval, tz: ?*timezone) void {
}
}
-pub const SeekError = error{
- Unseekable,
- Unexpected,
-};
+pub const SeekError = error{Unseekable} || UnexpectedError;
/// Repositions read/write file offset relative to the beginning.
pub fn lseek_SET(fd: fd_t, offset: u64) SeekError!void {
@@ -2382,9 +2328,7 @@ pub const RealPathError = error{
InvalidUtf8,
PathAlreadyExists,
-
- Unexpected,
-};
+} || UnexpectedError;
/// Return the canonicalized absolute pathname.
/// Expands all symbolic links and resolves references to `.`, `..`, and
@@ -2548,10 +2492,7 @@ pub fn dl_iterate_phdr(comptime T: type, callback: extern fn (info: *dl_phdr_inf
return last_r;
}
-pub const ClockGetTimeError = error{
- UnsupportedClock,
- Unexpected,
-};
+pub const ClockGetTimeError = error{UnsupportedClock} || UnexpectedError;
pub fn clock_gettime(clk_id: i32, tp: *timespec) ClockGetTimeError!void {
switch (errno(system.clock_gettime(clk_id, tp))) {
@@ -2571,10 +2512,7 @@ pub fn clock_getres(clk_id: i32, res: *timespec) ClockGetTimeError!void {
}
}
-pub const SchedGetAffinityError = error{
- PermissionDenied,
- Unexpected,
-};
+pub const SchedGetAffinityError = error{PermissionDenied} || UnexpectedError;
pub fn sched_getaffinity(pid: pid_t) SchedGetAffinityError!cpu_set_t {
var set: cpu_set_t = undefined;
@@ -2628,8 +2566,7 @@ pub const SigaltstackError = error{
/// Attempted to change the signal stack while it was active.
PermissionDenied,
- Unexpected,
-};
+} || UnexpectedError;
pub fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) SigaltstackError!void {
if (windows.is_the_target or uefi.is_the_target or wasi.is_the_target)
@@ -2677,9 +2614,7 @@ pub const FutimensError = error{
PermissionDenied,
ReadOnlyFileSystem,
-
- Unexpected,
-};
+} || UnexpectedError;
pub fn futimens(fd: fd_t, times: *const [2]timespec) FutimensError!void {
switch (errno(system.futimens(fd, times))) {
@@ -2694,10 +2629,7 @@ pub fn futimens(fd: fd_t, times: *const [2]timespec) FutimensError!void {
}
}
-pub const GetHostNameError = error{
- PermissionDenied,
- Unexpected,
-};
+pub const GetHostNameError = error{PermissionDenied} || UnexpectedError;
pub fn gethostname(name_buffer: *[HOST_NAME_MAX]u8) GetHostNameError![]u8 {
if (builtin.link_libc) {
diff --git a/lib/std/special/compiler_rt.zig b/lib/std/special/compiler_rt.zig
index 638a9bb60c..902f2da2ff 100644
--- a/lib/std/special/compiler_rt.zig
+++ b/lib/std/special/compiler_rt.zig
@@ -248,8 +248,17 @@ comptime {
switch (builtin.arch) {
.i386 => {
+ @export("_alldiv", @import("compiler_rt/aulldiv.zig")._alldiv, strong_linkage);
@export("_aulldiv", @import("compiler_rt/aulldiv.zig")._aulldiv, strong_linkage);
+ @export("_allrem", @import("compiler_rt/aullrem.zig")._allrem, strong_linkage);
@export("_aullrem", @import("compiler_rt/aullrem.zig")._aullrem, strong_linkage);
+
+ @export("__divti3", @import("compiler_rt/divti3.zig").__divti3, linkage);
+ @export("__modti3", @import("compiler_rt/modti3.zig").__modti3, linkage);
+ @export("__multi3", @import("compiler_rt/multi3.zig").__multi3, linkage);
+ @export("__udivti3", @import("compiler_rt/udivti3.zig").__udivti3, linkage);
+ @export("__udivmodti4", @import("compiler_rt/udivmodti4.zig").__udivmodti4, linkage);
+ @export("__umodti3", @import("compiler_rt/umodti3.zig").__umodti3, linkage);
},
.x86_64 => {
// The "ti" functions must use @Vector(2, u64) parameter types to adhere to the ABI
diff --git a/lib/std/special/compiler_rt/aulldiv.zig b/lib/std/special/compiler_rt/aulldiv.zig
index d99bc94ff5..dfca4f4c43 100644
--- a/lib/std/special/compiler_rt/aulldiv.zig
+++ b/lib/std/special/compiler_rt/aulldiv.zig
@@ -1,55 +1,76 @@
+const builtin = @import("builtin");
+
+pub extern stdcallcc fn _alldiv(a: i64, b: i64) i64 {
+ @setRuntimeSafety(builtin.is_test);
+ const s_a = a >> (i64.bit_count - 1);
+ const s_b = b >> (i64.bit_count - 1);
+
+ const an = (a ^ s_a) -% s_a;
+ const bn = (b ^ s_b) -% s_b;
+
+ const r = @bitCast(u64, an) / @bitCast(u64, bn);
+ const s = s_a ^ s_b;
+ return (@bitCast(i64, r) ^ s) -% s;
+}
+
pub nakedcc fn _aulldiv() void {
@setRuntimeSafety(false);
+
+ // The stack layout is:
+ // ESP+16 divisor (hi)
+ // ESP+12 divisor (low)
+ // ESP+8 dividend (hi)
+ // ESP+4 dividend (low)
+ // ESP return address
+
asm volatile (
- \\.intel_syntax noprefix
- \\
- \\ push ebx
- \\ push esi
- \\ mov eax,dword ptr [esp+18h]
- \\ or eax,eax
- \\ jne L1
- \\ mov ecx,dword ptr [esp+14h]
- \\ mov eax,dword ptr [esp+10h]
- \\ xor edx,edx
- \\ div ecx
- \\ mov ebx,eax
- \\ mov eax,dword ptr [esp+0Ch]
- \\ div ecx
- \\ mov edx,ebx
- \\ jmp L2
- \\ L1:
- \\ mov ecx,eax
- \\ mov ebx,dword ptr [esp+14h]
- \\ mov edx,dword ptr [esp+10h]
- \\ mov eax,dword ptr [esp+0Ch]
- \\ L3:
- \\ shr ecx,1
- \\ rcr ebx,1
- \\ shr edx,1
- \\ rcr eax,1
- \\ or ecx,ecx
- \\ jne L3
- \\ div ebx
- \\ mov esi,eax
- \\ mul dword ptr [esp+18h]
- \\ mov ecx,eax
- \\ mov eax,dword ptr [esp+14h]
- \\ mul esi
- \\ add edx,ecx
- \\ jb L4
- \\ cmp edx,dword ptr [esp+10h]
- \\ ja L4
- \\ jb L5
- \\ cmp eax,dword ptr [esp+0Ch]
- \\ jbe L5
- \\ L4:
- \\ dec esi
- \\ L5:
- \\ xor edx,edx
- \\ mov eax,esi
- \\ L2:
- \\ pop esi
- \\ pop ebx
- \\ ret 10h
+ \\ push %%ebx
+ \\ push %%esi
+ \\ mov 0x18(%%esp),%%eax
+ \\ or %%eax,%%eax
+ \\ jne 1f
+ \\ mov 0x14(%%esp),%%ecx
+ \\ mov 0x10(%%esp),%%eax
+ \\ xor %%edx,%%edx
+ \\ div %%ecx
+ \\ mov %%eax,%%ebx
+ \\ mov 0xc(%%esp),%%eax
+ \\ div %%ecx
+ \\ mov %%ebx,%%edx
+ \\ jmp 5f
+ \\ 1:
+ \\ mov %%eax,%%ecx
+ \\ mov 0x14(%%esp),%%ebx
+ \\ mov 0x10(%%esp),%%edx
+ \\ mov 0xc(%%esp),%%eax
+ \\ 2:
+ \\ shr %%ecx
+ \\ rcr %%ebx
+ \\ shr %%edx
+ \\ rcr %%eax
+ \\ or %%ecx,%%ecx
+ \\ jne 2b
+ \\ div %%ebx
+ \\ mov %%eax,%%esi
+ \\ mull 0x18(%%esp)
+ \\ mov %%eax,%%ecx
+ \\ mov 0x14(%%esp),%%eax
+ \\ mul %%esi
+ \\ add %%ecx,%%edx
+ \\ jb 3f
+ \\ cmp 0x10(%%esp),%%edx
+ \\ ja 3f
+ \\ jb 4f
+ \\ cmp 0xc(%%esp),%%eax
+ \\ jbe 4f
+ \\ 3:
+ \\ dec %%esi
+ \\ 4:
+ \\ xor %%edx,%%edx
+ \\ mov %%esi,%%eax
+ \\ 5:
+ \\ pop %%esi
+ \\ pop %%ebx
+ \\ ret $0x10
);
}
diff --git a/lib/std/special/compiler_rt/aullrem.zig b/lib/std/special/compiler_rt/aullrem.zig
index 51c4eebe3e..c1fee72032 100644
--- a/lib/std/special/compiler_rt/aullrem.zig
+++ b/lib/std/special/compiler_rt/aullrem.zig
@@ -1,56 +1,77 @@
+const builtin = @import("builtin");
+
+pub extern stdcallcc fn _allrem(a: i64, b: i64) i64 {
+ @setRuntimeSafety(builtin.is_test);
+ const s_a = a >> (i64.bit_count - 1);
+ const s_b = b >> (i64.bit_count - 1);
+
+ const an = (a ^ s_a) -% s_a;
+ const bn = (b ^ s_b) -% s_b;
+
+ const r = @bitCast(u64, an) % @bitCast(u64, bn);
+ const s = s_a ^ s_b;
+ return (@bitCast(i64, r) ^ s) -% s;
+}
+
pub nakedcc fn _aullrem() void {
@setRuntimeSafety(false);
+
+ // The stack layout is:
+ // ESP+16 divisor (hi)
+ // ESP+12 divisor (low)
+ // ESP+8 dividend (hi)
+ // ESP+4 dividend (low)
+ // ESP return address
+
asm volatile (
- \\.intel_syntax noprefix
- \\
- \\ push ebx
- \\ mov eax,dword ptr [esp+14h]
- \\ or eax,eax
- \\ jne L1a
- \\ mov ecx,dword ptr [esp+10h]
- \\ mov eax,dword ptr [esp+0Ch]
- \\ xor edx,edx
- \\ div ecx
- \\ mov eax,dword ptr [esp+8]
- \\ div ecx
- \\ mov eax,edx
- \\ xor edx,edx
- \\ jmp L2a
- \\ L1a:
- \\ mov ecx,eax
- \\ mov ebx,dword ptr [esp+10h]
- \\ mov edx,dword ptr [esp+0Ch]
- \\ mov eax,dword ptr [esp+8]
- \\ L3a:
- \\ shr ecx,1
- \\ rcr ebx,1
- \\ shr edx,1
- \\ rcr eax,1
- \\ or ecx,ecx
- \\ jne L3a
- \\ div ebx
- \\ mov ecx,eax
- \\ mul dword ptr [esp+14h]
- \\ xchg eax,ecx
- \\ mul dword ptr [esp+10h]
- \\ add edx,ecx
- \\ jb L4a
- \\ cmp edx,dword ptr [esp+0Ch]
- \\ ja L4a
- \\ jb L5a
- \\ cmp eax,dword ptr [esp+8]
- \\ jbe L5a
- \\ L4a:
- \\ sub eax,dword ptr [esp+10h]
- \\ sbb edx,dword ptr [esp+14h]
- \\ L5a:
- \\ sub eax,dword ptr [esp+8]
- \\ sbb edx,dword ptr [esp+0Ch]
- \\ neg edx
- \\ neg eax
- \\ sbb edx,0
- \\ L2a:
- \\ pop ebx
- \\ ret 10h
+ \\ push %%ebx
+ \\ mov 0x14(%%esp),%%eax
+ \\ or %%eax,%%eax
+ \\ jne 1f
+ \\ mov 0x10(%%esp),%%ecx
+ \\ mov 0xc(%%esp),%%eax
+ \\ xor %%edx,%%edx
+ \\ div %%ecx
+ \\ mov 0x8(%%esp),%%eax
+ \\ div %%ecx
+ \\ mov %%edx,%%eax
+ \\ xor %%edx,%%edx
+ \\ jmp 6f
+ \\ 1:
+ \\ mov %%eax,%%ecx
+ \\ mov 0x10(%%esp),%%ebx
+ \\ mov 0xc(%%esp),%%edx
+ \\ mov 0x8(%%esp),%%eax
+ \\ 2:
+ \\ shr %%ecx
+ \\ rcr %%ebx
+ \\ shr %%edx
+ \\ rcr %%eax
+ \\ or %%ecx,%%ecx
+ \\ jne 2b
+ \\ div %%ebx
+ \\ mov %%eax,%%ecx
+ \\ mull 0x14(%%esp)
+ \\ xchg %%eax,%%ecx
+ \\ mull 0x10(%%esp)
+ \\ add %%ecx,%%edx
+ \\ jb 3f
+ \\ cmp 0xc(%%esp),%%edx
+ \\ ja 3f
+ \\ jb 4f
+ \\ cmp 0x8(%%esp),%%eax
+ \\ jbe 4f
+ \\ 3:
+ \\ sub 0x10(%%esp),%%eax
+ \\ sbb 0x14(%%esp),%%edx
+ \\ 4:
+ \\ sub 0x8(%%esp),%%eax
+ \\ sbb 0xc(%%esp),%%edx
+ \\ neg %%edx
+ \\ neg %%eax
+ \\ sbb $0x0,%%edx
+ \\ 6:
+ \\ pop %%ebx
+ \\ ret $0x10
);
}
diff --git a/lib/std/special/compiler_rt/extendXfYf2_test.zig b/lib/std/special/compiler_rt/extendXfYf2_test.zig
index 050a799823..6f8111c8fb 100644
--- a/lib/std/special/compiler_rt/extendXfYf2_test.zig
+++ b/lib/std/special/compiler_rt/extendXfYf2_test.zig
@@ -1,3 +1,4 @@
+const builtin = @import("builtin");
const __extenddftf2 = @import("extendXfYf2.zig").__extenddftf2;
const __extendhfsf2 = @import("extendXfYf2.zig").__extendhfsf2;
const __extendsftf2 = @import("extendXfYf2.zig").__extendsftf2;
@@ -87,7 +88,10 @@ test "extenddftf2" {
test "extendhfsf2" {
test__extendhfsf2(0x7e00, 0x7fc00000); // qNaN
test__extendhfsf2(0x7f00, 0x7fe00000); // sNaN
- test__extendhfsf2(0x7c01, 0x7f802000); // sNaN
+ // On x86 the NaN becomes quiet because the return is pushed on the x87
+ // stack due to ABI requirements
+ if (builtin.arch != .i386 and builtin.os == .windows)
+ test__extendhfsf2(0x7c01, 0x7f802000); // sNaN
test__extendhfsf2(0, 0); // 0
test__extendhfsf2(0x8000, 0x80000000); // -0
diff --git a/lib/std/special/doc/index.html b/lib/std/special/doc/index.html
deleted file mode 100644
index db80ec9550..0000000000
--- a/lib/std/special/doc/index.html
+++ /dev/null
@@ -1,85 +0,0 @@
-<!doctype html>
-<html>
- <head>
- <meta charset="utf-8">
- <title>Documentation - Zig</title>
- <link rel="icon" href="favicon.png">
- <style type="text/css">
- body {
- font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
- }
- .hidden {
- display: none;
- }
- a {
- color: #2A6286;
- }
- pre{
- font-family:"Source Code Pro",monospace;
- font-size:1em;
- background-color:#F5F5F5;
- padding:1em;
- }
- #listNav {
- list-style-type: none;
- margin: 0;
- padding: 0;
- overflow: hidden;
- background-color: #333;
- }
- #listNav li {
- float:left;
- }
- #listNav li a {
- display: block;
- color: #fff;
- text-align: center;
- padding: .8em .8em;
- text-decoration: none;
- }
- #listNav li a:hover {
- background-color: #111;
- }
- #listNav li a.active {
- background-color: #4CAF50;
- }
-
- @media (prefers-color-scheme: dark) {
- body{
- background-color: #111;
- color: #bbb;
- }
- a {
- color: #88f;
- }
- pre{
- background-color:#2A2A2A;
- }
- }
- </style>
- </head>
- <body>
- <p id="status">Loading...</p>
- <div id="sectNav" class="hidden"><ul id="listNav"></ul></div>
- <div id="fnProto" class="hidden">
- <pre id="fnProtoCode"></pre>
- </div>
- <div id="sectPkgs" class="hidden">
- <h2>Packages</h2>
- <ul id="listPkgs">
- </ul>
- </div>
- <div id="sectTypes" class="hidden">
- <h2>Types</h2>
- <ul id="listTypes">
- </ul>
- </div>
- <div id="sectFns" class="hidden">
- <h2>Functions</h2>
- <ul id="listFns">
- </ul>
- </div>
- <script src="data.js"></script>
- <script src="main.js"></script>
- </body>
-</html>
diff --git a/lib/std/special/doc/main.js b/lib/std/special/doc/main.js
deleted file mode 100644
index 50002f6841..0000000000
--- a/lib/std/special/doc/main.js
+++ /dev/null
@@ -1,382 +0,0 @@
-(function() {
- var domStatus = document.getElementById("status");
- var domSectNav = document.getElementById("sectNav");
- var domListNav = document.getElementById("listNav");
- var domSectPkgs = document.getElementById("sectPkgs");
- var domListPkgs = document.getElementById("listPkgs");
- var domSectTypes = document.getElementById("sectTypes");
- var domListTypes = document.getElementById("listTypes");
- var domSectFns = document.getElementById("sectFns");
- var domListFns = document.getElementById("listFns");
- var domFnProto = document.getElementById("fnProto");
- var domFnProtoCode = document.getElementById("fnProtoCode");
-
- var typeKindTypeId;
- var typeKindFnId;
- findTypeKinds();
-
- // for each package, is an array with packages to get to this one
- var canonPkgPaths = computeCanonicalPackagePaths();
-
- var curNav = {
- // each element is a package name, e.g. @import("a") then within there @import("b")
- // starting implicitly from root package
- pkgNames: [],
- // same as above except actual packages, not names
- pkgObjs: [],
- // Each element is a decl name, `a.b.c`, a is 0, b is 1, c is 2, etc.
- // empty array means refers to the package itself
- declNames: [],
- // these will be all types, except the last one may be a type or a decl
- declObjs: [],
- };
-
- var rootIsStd = detectRootIsStd();
- var typeTypeId = findTypeTypeId();
- window.addEventListener('hashchange', onHashChange, false);
- onHashChange();
-
- function renderTitle() {
- var list = curNav.pkgNames.concat(curNav.declNames);
- var suffix = " - Zig";
- if (list.length === 0) {
- if (rootIsStd) {
- document.title = "std" + suffix;
- } else {
- document.title = zigAnalysis.params.rootName + suffix;
- }
- } else {
- document.title = list.join('.') + suffix;
- }
- }
-
- function render() {
- domStatus.classList.add("hidden");
- domFnProto.classList.add("hidden");
-
- renderTitle();
-
- var pkg = zigAnalysis.packages[zigAnalysis.rootPkg];
- curNav.pkgObjs = [pkg];
- for (var i = 0; i < curNav.pkgNames.length; i += 1) {
- var childPkg = zigAnalysis.packages[pkg.table[curNav.pkgNames[i]]];
- if (childPkg == null) {
- return render404();
- }
- pkg = childPkg;
- curNav.pkgObjs.push(pkg);
- }
-
- var decl = zigAnalysis.types[pkg.main];
- curNav.declObjs = [decl];
- for (var i = 0; i < curNav.declNames.length; i += 1) {
- var childDecl = findSubDecl(decl, curNav.declNames[i]);
- if (childDecl == null) {
- return render404();
- }
- var container = getDeclContainerType(childDecl);
- if (container == null) {
- if (i + 1 === curNav.declNames.length) {
- curNav.declObjs.push(childDecl);
- break;
- } else {
- return render404();
- }
- }
- decl = container;
- curNav.declObjs.push(decl);
- }
-
- renderNav();
-
- var lastPkg = curNav.pkgObjs[curNav.pkgObjs.length - 1];
- renderPkgList(lastPkg);
-
- var lastDecl = curNav.declObjs[curNav.declObjs.length - 1];
- if (lastDecl.pubDecls != null) {
- return renderContainer(lastDecl);
- } else if (lastDecl.type != null) {
- var typeObj = zigAnalysis.types[lastDecl.type];
- if (typeObj.kind === typeKindFnId) {
- return renderFn(lastDecl);
- }
- throw new Error("docs for this decl which is not a container");
- } else {
- throw new Error("docs for this decl which is a type");
- }
- }
-
- function renderFn(fnDecl) {
- domSectPkgs.classList.add("hidden");
- domSectTypes.classList.add("hidden");
- domSectFns.classList.add("hidden");
-
- var typeObj = zigAnalysis.types[fnDecl.type];
- domFnProtoCode.textContent = "fn " + fnDecl.name + typeObj.name.substring(2);
-
- domFnProto.classList.remove("hidden");
- }
-
- function renderNav() {
- var len = curNav.pkgNames.length + curNav.declNames.length;
- resizeDomList(domListNav, len, '<li><a href="#"></a></li>');
- var list = [];
- var hrefPkgNames = [];
- var hrefDeclNames = [];
- for (var i = 0; i < curNav.pkgNames.length; i += 1) {
- hrefPkgNames.push(curNav.pkgNames[i]);
- list.push({
- name: curNav.pkgNames[i],
- link: navLink(hrefPkgNames, hrefDeclNames),
- });
- }
- for (var i = 0; i < curNav.declNames.length; i += 1) {
- hrefDeclNames.push(curNav.declNames[i]);
- list.push({
- name: curNav.declNames[i],
- link: navLink(hrefPkgNames, hrefDeclNames),
- });
- }
-
- for (var i = 0; i < list.length; i += 1) {
- var liDom = domListNav.children[i];
- var aDom = liDom.children[0];
- aDom.textContent = list[i].name;
- aDom.setAttribute('href', list[i].link);
- if (i + 1 == list.length) {
- aDom.classList.add("active");
- } else {
- aDom.classList.remove("active");
- }
- }
-
- domSectNav.classList.remove("hidden");
- }
-
- function render404() {
- domStatus.textContent = "404 Not Found";
- domStatus.classList.remove("hidden");
- domSectPkgs.classList.add("hidden");
- domSectTypes.classList.add("hidden");
- domSectFns.classList.add("hidden");
- domFnProto.classList.add("hidden");
- }
-
- function renderPkgList(pkg) {
- var list = [];
- for (var key in pkg.table) {
- if (key === "root" && rootIsStd) continue;
- list.push({
- name: key,
- pkg: pkg.table[key],
- });
- }
- list.sort(function(a, b) {
- return operatorCompare(a.name.toLowerCase(), b.name.toLowerCase());
- });
-
- if (list.length === 0) {
- domSectPkgs.classList.add("hidden");
- } else {
- resizeDomList(domListPkgs, list.length, '<li><a href="#"></a></li>');
- for (var i = 0; i < list.length; i += 1) {
- var liDom = domListPkgs.children[i];
- var aDom = liDom.children[0];
- aDom.textContent = list[i].name;
- aDom.setAttribute('href', navLinkPkg(list[i].pkg));
- }
-
- domSectPkgs.classList.remove("hidden");
- }
- }
-
- function navLink(pkgNames, declNames) {
- if (pkgNames.length === 0 && declNames.length === 0) {
- return '#';
- } else if (declNames.length === 0) {
- return '#' + pkgNames.join('.');
- } else {
- return '#' + pkgNames.join('.') + ';' + declNames.join('.');
- }
- }
-
- function navLinkPkg(pkgIndex) {
- return navLink(canonPkgPaths[pkgIndex], []);
- }
-
- function navLinkDecl(childName) {
- return navLink(curNav.pkgNames, curNav.declNames.concat([childName]));
- }
-
- function resizeDomList(listDom, desiredLen, templateHtml) {
- // add the missing dom entries
- var i, ev;
- for (i = listDom.childElementCount; i < desiredLen; i += 1) {
- listDom.insertAdjacentHTML('beforeend', templateHtml);
- }
- // remove extra dom entries
- while (desiredLen < listDom.childElementCount) {
- listDom.removeChild(listDom.lastChild);
- }
- }
-
- function renderContainer(container) {
- var typesList = [];
- var fnsList = [];
- for (var i = 0; i < container.pubDecls.length; i += 1) {
- var decl = zigAnalysis.decls[container.pubDecls[i]];
- if (decl.type != null) {
- if (decl.type == typeTypeId) {
- typesList.push(decl);
- } else {
- var typeKind = zigAnalysis.types[decl.type].kind;
- if (typeKind === typeKindFnId) {
- fnsList.push(decl);
- }
- }
- }
- }
- typesList.sort(function(a, b) {
- return operatorCompare(a.name.toLowerCase(), b.name.toLowerCase());
- });
- fnsList.sort(function(a, b) {
- return operatorCompare(a.name.toLowerCase(), b.name.toLowerCase());
- });
-
- if (typesList.length === 0) {
- domSectTypes.classList.add("hidden");
- } else {
- resizeDomList(domListTypes, typesList.length, '<li><a href="#"></a></li>');
- for (var i = 0; i < typesList.length; i += 1) {
- var liDom = domListTypes.children[i];
- var aDom = liDom.children[0];
- var decl = typesList[i];
- aDom.textContent = decl.name;
- aDom.setAttribute('href', navLinkDecl(decl.name));
- }
- domSectTypes.classList.remove("hidden");
- }
-
- if (fnsList.length === 0) {
- domSectFns.classList.add("hidden");
- } else {
- resizeDomList(domListFns, fnsList.length, '<li><a href="#"></a></li>');
- for (var i = 0; i < fnsList.length; i += 1) {
- var liDom = domListFns.children[i];
- var aDom = liDom.children[0];
- var decl = fnsList[i];
- aDom.textContent = decl.name;
- aDom.setAttribute('href', navLinkDecl(decl.name));
- }
- domSectFns.classList.remove("hidden");
- }
- }
-
- function operatorCompare(a, b) {
- if (a === b) {
- return 0;
- } else if (a < b) {
- return -1;
- } else {
- return 1;
- }
- }
-
- function detectRootIsStd() {
- var rootPkg = zigAnalysis.packages[zigAnalysis.rootPkg];
- if (rootPkg.table["std"] == null) {
- // no std mapped into the root package
- return false;
- }
- var stdPkg = zigAnalysis.packages[rootPkg.table["std"]];
- return rootPkg.file === stdPkg.file;
- }
-
- function findTypeKinds() {
- for (var i = 0; i < zigAnalysis.typeKinds.length; i += 1) {
- if (zigAnalysis.typeKinds[i] === "Type") {
- typeKindTypeId = i;
- } else if (zigAnalysis.typeKinds[i] === "Fn") {
- typeKindFnId = i;
- }
- }
- if (typeKindTypeId == null) {
- throw new Error("No type kind 'Type' found");
- }
- if (typeKindFnId == null) {
- throw new Error("No type kind 'Fn' found");
- }
- }
-
- function findTypeTypeId() {
- for (var i = 0; i < zigAnalysis.types.length; i += 1) {
- if (zigAnalysis.types[i].kind == typeKindTypeId) {
- return i;
- }
- }
- throw new Error("No type 'type' found");
- }
-
- function onHashChange() {
- curNav = {
- pkgNames: [],
- pkgObjs: [],
- declNames: [],
- declObjs: [],
- };
- if (location.hash[0] === '#' && location.hash.length > 1) {
- var parts = location.hash.substring(1).split(";");
- curNav.pkgNames = parts[0].split(".");
- if (parts[1] != null) {
- curNav.declNames = parts[1].split(".");
- }
- }
- render();
- }
-
- function findSubDecl(parentType, childName) {
- if (parentType.pubDecls == null) throw new Error("parent object has no public decls");
- for (var i = 0; i < parentType.pubDecls.length; i += 1) {
- var declIndex = parentType.pubDecls[i];
- var childDecl = zigAnalysis.decls[declIndex];
- if (childDecl.name === childName) {
- return childDecl;
- }
- }
- return null;
- }
-
- function getDeclContainerType(decl) {
- if (decl.type === typeTypeId) {
- return zigAnalysis.types[decl.value];
- }
- return null;
- }
-
- function computeCanonicalPackagePaths() {
- var list = new Array(zigAnalysis.packages.length);
- // Now we try to find all the packages from root.
- var rootPkg = zigAnalysis.packages[zigAnalysis.rootPkg];
- // Breadth-first to keep the path shortest possible.
- var stack = [{
- path: [],
- pkg: rootPkg,
- }];
- while (stack.length !== 0) {
- var item = stack.pop();
- for (var key in item.pkg.table) {
- var childPkgIndex = item.pkg.table[key];
- if (list[childPkgIndex] != null) continue;
-
- var newPath = item.path.concat([key])
- list[childPkgIndex] = newPath;
- var childPkg = zigAnalysis.packages[childPkgIndex];
- stack.push({
- path: newPath,
- pkg: childPkg,
- });
- }
- }
- return list;
- }
-})();
diff --git a/lib/std/special/docs/index.html b/lib/std/special/docs/index.html
new file mode 100644
index 0000000000..2508308ced
--- /dev/null
+++ b/lib/std/special/docs/index.html
@@ -0,0 +1,356 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Documentation - Zig</title>
+ <link rel="icon" href="favicon.png">
+ <style type="text/css">
+ body {
+ font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
+ max-width: 60em;
+ }
+ .hidden {
+ display: none;
+ }
+ a {
+ color: #2A6286;
+ }
+ pre{
+ font-family:"Source Code Pro",monospace;
+ font-size:1em;
+ background-color:#F5F5F5;
+ padding:1em;
+ overflow-x: auto;
+ }
+ code {
+ font-family:"Source Code Pro",monospace;
+ font-size:1em;
+ }
+ nav {
+ width: 10em;
+ position: fixed;
+ left: 0;
+ top: 0;
+ height: 100vh;
+ overflow: auto;
+ }
+ nav h2 {
+ font-size: 1.2em;
+ text-decoration: underline;
+ margin: 0;
+ padding: 0.5em 0;
+ text-align: center;
+ }
+ nav p {
+ margin: 0;
+ padding: 0;
+ text-align: center;
+ }
+ section {
+ margin-left: 10em;
+ }
+ section h1 {
+ border-bottom: 1px dashed;
+ }
+ section h2 {
+ font-size: 1.3em;
+ margin: 0.5em 0;
+ padding: 0;
+ border-bottom: 1px solid;
+ }
+ #listNav {
+ list-style-type: none;
+ margin: 0.5em 0 0 0;
+ padding: 0;
+ overflow: hidden;
+ background-color: #f1f1f1;
+ }
+ #listNav li {
+ float:left;
+ }
+ #listNav li a {
+ display: block;
+ color: #000;
+ text-align: center;
+ padding: .5em .8em;
+ text-decoration: none;
+ }
+ #listNav li a:hover {
+ background-color: #555;
+ color: #fff;
+ }
+ #listNav li a.active {
+ background-color: #FFBB4D;
+ color: #000;
+ }
+
+ #listPkgs {
+ list-style-type: none;
+ margin: 0;
+ padding: 0;
+ background-color: #f1f1f1;
+ }
+ #listPkgs li a {
+ display: block;
+ color: #000;
+ padding: 0.5em 1em;
+ text-decoration: none;
+ }
+ #listPkgs li a:hover {
+ background-color: #555;
+ color: #fff;
+ }
+ #listPkgs li a.active {
+ background-color: #FFBB4D;
+ color: #000;
+ }
+ #logo {
+ width: 8em;
+ padding: 0.5em 1em;
+ }
+
+ #search {
+ width: 100%;
+ }
+
+ #helpDialog {
+ width: 21em;
+ height: 19em;
+ position: fixed;
+ top: 0;
+ left: 0;
+ background-color: #333;
+ color: #fff;
+ border: 1px solid #fff;
+ }
+ #helpDialog h1 {
+ text-align: center;
+ font-size: 1.5em;
+ }
+ dt, dd {
+ display: inline;
+ margin: 0 0.2em;
+ }
+ kbd {
+ color: #000;
+ background-color: #fafbfc;
+ border-color: #d1d5da;
+ border-bottom-color: #c6cbd1;
+ box-shadow-color: #c6cbd1;
+ display: inline-block;
+ padding: 0.3em 0.2em;
+ font: 1.2em monospace;
+ line-height: 0.8em;
+ vertical-align: middle;
+ border: solid 1px;
+ border-radius: 3px;
+ box-shadow: inset 0 -1px 0;
+ cursor: default;
+ }
+
+ #listSearchResults li.selected {
+ background-color: #93e196;
+ }
+
+ #tableFnErrors tr td:first-child{
+ text-align: right;
+ font-weight: bold;
+ vertical-align: top;
+ }
+
+ #sectGlobalVars td, #sectFns td {
+ vertical-align: top;
+ margin: 0;
+ padding: 0.5em;
+ max-width: 20em;
+ text-overflow: ellipsis;
+ overflow-x: hidden;
+ }
+
+ .tok-kw {
+ color: #333;
+ font-weight: bold;
+ }
+ .tok-str {
+ color: #d14;
+ }
+ .tok-builtin {
+ color: #0086b3;
+ }
+ .tok-comment {
+ color: #777;
+ font-style: italic;
+ }
+ .tok-fn {
+ color: #900;
+ font-weight: bold;
+ }
+ .tok-null {
+ color: #008080;
+ }
+ .tok-number {
+ color: #008080;
+ }
+ .tok-type {
+ color: #458;
+ font-weight: bold;
+ }
+
+ @media (prefers-color-scheme: dark) {
+ body{
+ background-color: #111;
+ color: #bbb;
+ }
+ a {
+ color: #88f;
+ }
+ pre{
+ background-color:#2A2A2A;
+ }
+ #listNav {
+ background-color: #333;
+ }
+ #listNav li a {
+ color: #fff;
+ }
+ #listNav li a:hover {
+ background-color: #555;
+ color: #fff;
+ }
+ #listNav li a.active {
+ background-color: #FFBB4D;
+ color: #000;
+ }
+ #listPkgs {
+ background-color: #333;
+ }
+ #listPkgs li a {
+ color: #fff;
+ }
+ #listPkgs li a:hover {
+ background-color: #555;
+ color: #fff;
+ }
+ #listPkgs li a.active {
+ background-color: #FFBB4D;
+ color: #000;
+ }
+ #listSearchResults li.selected {
+ background-color: #000;
+ }
+ #listSearchResults li.selected a {
+ color: #fff;
+ }
+ .tok-kw {
+ color: #eee;
+ }
+ .tok-str {
+ color: #2e5;
+ }
+ .tok-builtin {
+ color: #ff894c;
+ }
+ .tok-comment {
+ color: #aa7;
+ }
+ .tok-fn {
+ color: #e33;
+ }
+ .tok-null {
+ color: #ff8080;
+ }
+ .tok-number {
+ color: #ff8080;
+ }
+ .tok-type {
+ color: #68f;
+ }
+ }
+ </style>
+ </head>
+ <body>
+ <nav>
+ <img alt="ZIG" id="logo" src="data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHZpZXdCb3g9IjAgMCAxNTAgMTAwIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxnIGZpbGw9IiNmN2E0MWQiPjxwYXRoIGQ9Im0wIDEwdjgwaDE5bDYtMTAgMTItMTBoLTE3di00MGgxNXYtMjB6bTQwIDB2MjBoNjJ2LTIwem05MSAwLTYgMTAtMTIgMTBoMTd2NDBoLTE1djIwaDM1di04MHptLTgzIDYwdjIwaDYydi0yMHoiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwYXRoIGQ9Im0zNyA3MC0xOCAyMHYtMTV6Ii8+PHBhdGggZD0ibTExMyAzMCAxOC0yMHYxNXoiLz48cGF0aCBkPSJtOTYuOTggMTAuNjMgMzYuMjgtMTAuNC04MC4yOSA4OS4xNy0zNi4yOCAxMC40eiIvPjwvZz48L3N2Zz4K"></img>
+ <div id="sectPkgs" class="hidden">
+ <h2>Packages</h2>
+ <ul id="listPkgs">
+ </ul>
+ </div>
+ <div id="sectInfo" class="hidden">
+ <h2>Zig Version</h2>
+ <p id="tdZigVer"></p>
+ <h2>Target</h2>
+ <p id="tdTarget"></p>
+ </div>
+ </nav>
+ <section>
+ <input type="search" id="search" autocomplete="off" spellcheck="false" placeholder="`s` to search, `?` to see more options">
+ <p id="status">Loading...</p>
+ <div id="sectNav" class="hidden"><ul id="listNav"></ul></div>
+ <div id="fnProto" class="hidden">
+ <pre id="fnProtoCode"></pre>
+ </div>
+ <h1 id="hdrName" class="hidden"></h1>
+ <div id="fnDocs" class="hidden"></div>
+ <div id="sectFnErrors" class="hidden">
+ <h2>Errors</h2>
+ <div id="fnErrorsAnyError">
+ <p><span class="tok-type">anyerror</span> means the error set is known only at runtime.</p>
+ </div>
+ <table id="tableFnErrors"><tbody id="listFnErrors"></tbody></table>
+ </div>
+ <div id="fnExamples" class="hidden"></div>
+ <div id="fnNoExamples" class="hidden">
+ <p>This function is not tested or referenced.</p>
+ </div>
+ <div id="sectSearchResults" class="hidden">
+ <h2>Search Results</h2>
+ <ul id="listSearchResults"></ul>
+ </div>
+ <div id="sectSearchNoResults" class="hidden">
+ <h2>No Results Found</h2>
+ <p>Press escape to exit search and then '?' to see more options.</p>
+ </div>
+ <div id="sectFields" class="hidden">
+ <h2>Fields</h2>
+ <ul id="listFields">
+ </ul>
+ </div>
+ <div id="sectTypes" class="hidden">
+ <h2>Types</h2>
+ <ul id="listTypes">
+ </ul>
+ </div>
+ <div id="sectGlobalVars" class="hidden">
+ <h2>Global Variables</h2>
+ <table>
+ <tbody id="listGlobalVars">
+ </tbody>
+ </table>
+ </div>
+ <div id="sectFns" class="hidden">
+ <h2>Functions</h2>
+ <table>
+ <tbody id="listFns">
+ </tbody>
+ </table>
+ </div>
+ <div id="sectErrSets" class="hidden">
+ <h2>Error Sets</h2>
+ <ul id="listErrSets">
+ </ul>
+ </div>
+ </section>
+ <div id="helpDialog" class="hidden">
+ <h1>Keyboard Shortcuts</h1>
+ <dl><dt><kbd>?</kbd></dt><dd>Show this help dialog</dd></dl>
+ <dl><dt><kbd>Esc</kbd></dt><dd>Clear focus; close this dialog</dd></dl>
+ <dl><dt><kbd>s</kbd></dt><dd>Focus the search field</dd></dl>
+ <dl><dt><kbd>↑</kbd></dt><dd>Move up in search results</dd></dl>
+ <dl><dt><kbd>↓</kbd></dt><dd>Move down in search results</dd></dl>
+ <dl><dt><kbd>⏎</kbd></dt><dd>Go to active search result</dd></dl>
+ </div>
+ <script src="data.js"></script>
+ <script src="main.js"></script>
+ </body>
+</html>
diff --git a/lib/std/special/docs/main.js b/lib/std/special/docs/main.js
new file mode 100644
index 0000000000..5d6e006748
--- /dev/null
+++ b/lib/std/special/docs/main.js
@@ -0,0 +1,1194 @@
+(function() {
+ var domStatus = document.getElementById("status");
+ var domSectNav = document.getElementById("sectNav");
+ var domListNav = document.getElementById("listNav");
+ var domSectPkgs = document.getElementById("sectPkgs");
+ var domListPkgs = document.getElementById("listPkgs");
+ var domSectTypes = document.getElementById("sectTypes");
+ var domListTypes = document.getElementById("listTypes");
+ var domSectErrSets = document.getElementById("sectErrSets");
+ var domListErrSets = document.getElementById("listErrSets");
+ var domSectFns = document.getElementById("sectFns");
+ var domListFns = document.getElementById("listFns");
+ var domSectFields = document.getElementById("sectFields");
+ var domListFields = document.getElementById("listFields");
+ var domSectGlobalVars = document.getElementById("sectGlobalVars");
+ var domListGlobalVars = document.getElementById("listGlobalVars");
+ var domFnProto = document.getElementById("fnProto");
+ var domFnProtoCode = document.getElementById("fnProtoCode");
+ var domFnDocs = document.getElementById("fnDocs");
+ var domSectFnErrors = document.getElementById("sectFnErrors");
+ var domListFnErrors = document.getElementById("listFnErrors");
+ var domTableFnErrors = document.getElementById("tableFnErrors");
+ var domFnErrorsAnyError = document.getElementById("fnErrorsAnyError");
+ var domFnExamples = document.getElementById("fnExamples");
+ var domFnNoExamples = document.getElementById("fnNoExamples");
+ var domSearch = document.getElementById("search");
+ var domSectSearchResults = document.getElementById("sectSearchResults");
+ var domListSearchResults = document.getElementById("listSearchResults");
+ var domSectSearchNoResults = document.getElementById("sectSearchNoResults");
+ var domSectInfo = document.getElementById("sectInfo");
+ var domListInfo = document.getElementById("listInfo");
+ var domTdTarget = document.getElementById("tdTarget");
+ var domTdZigVer = document.getElementById("tdZigVer");
+ var domHdrName = document.getElementById("hdrName");
+ var domHelpModal = document.getElementById("helpDialog");
+
+ var searchTimer = null;
+ var escapeHtmlReplacements = { "&": "&amp;", '"': "&quot;", "<": "&lt;", ">": "&gt;" };
+
+ var typeKindTypeId;
+ var typeKindFnId;
+ var typeKindPtrId;
+ var typeKindFloatId;
+ var typeKindIntId;
+ var typeKindBoolId;
+ var typeKindVoidId;
+ var typeKindErrSetId;
+ var typeKindErrUnionId;
+ findTypeKinds();
+
+ // for each package, is an array with packages to get to this one
+ var canonPkgPaths = computeCanonicalPackagePaths();
+ // for each decl, is an array with {declNames, pkgNames} to get to this one
+ var canonDeclPaths = null; // lazy; use getCanonDeclPath
+ // for each type, is an array with {declNames, pkgNames} to get to this one
+ var canonTypeDecls = null; // lazy; use getCanonTypeDecl
+
+ var curNav = {
+ // each element is a package name, e.g. @import("a") then within there @import("b")
+ // starting implicitly from root package
+ pkgNames: [],
+ // same as above except actual packages, not names
+ pkgObjs: [],
+ // Each element is a decl name, `a.b.c`, a is 0, b is 1, c is 2, etc.
+ // empty array means refers to the package itself
+ declNames: [],
+ // these will be all types, except the last one may be a type or a decl
+ declObjs: [],
+ };
+ var curNavSearch = "";
+ var curSearchIndex = -1;
+
+ var rootIsStd = detectRootIsStd();
+ var typeTypeId = findTypeTypeId();
+
+ // map of decl index to list of non-generic fn indexes
+ var nodesToFnsMap = indexNodesToFns();
+ // map of decl index to list of comptime fn calls
+ var nodesToCallsMap = indexNodesToCalls();
+
+ domSearch.addEventListener('keydown', onSearchKeyDown, false);
+ window.addEventListener('hashchange', onHashChange, false);
+ window.addEventListener('keydown', onWindowKeyDown, false);
+ onHashChange();
+
+ function renderTitle() {
+ var list = curNav.pkgNames.concat(curNav.declNames);
+ var suffix = " - Zig";
+ if (list.length === 0) {
+ if (rootIsStd) {
+ document.title = "std" + suffix;
+ } else {
+ document.title = zigAnalysis.params.rootName + suffix;
+ }
+ } else {
+ document.title = list.join('.') + suffix;
+ }
+ }
+
+ function render() {
+ domStatus.classList.add("hidden");
+ domFnProto.classList.add("hidden");
+ domFnDocs.classList.add("hidden");
+ domSectPkgs.classList.add("hidden");
+ domSectTypes.classList.add("hidden");
+ domSectErrSets.classList.add("hidden");
+ domSectFns.classList.add("hidden");
+ domSectFields.classList.add("hidden");
+ domSectSearchResults.classList.add("hidden");
+ domSectSearchNoResults.classList.add("hidden");
+ domSectInfo.classList.add("hidden");
+ domHdrName.classList.add("hidden");
+ domSectNav.classList.add("hidden");
+ domSectFnErrors.classList.add("hidden");
+ domFnExamples.classList.add("hidden");
+ domFnNoExamples.classList.add("hidden");
+ domFnErrorsAnyError.classList.add("hidden");
+ domTableFnErrors.classList.add("hidden");
+ domSectGlobalVars.classList.add("hidden");
+
+ renderTitle();
+ renderInfo();
+ renderPkgList();
+
+ if (curNavSearch !== "") {
+ return renderSearch();
+ }
+
+ var rootPkg = zigAnalysis.packages[zigAnalysis.rootPkg];
+ var pkg = rootPkg;
+ curNav.pkgObjs = [pkg];
+ for (var i = 0; i < curNav.pkgNames.length; i += 1) {
+ var childPkg = zigAnalysis.packages[pkg.table[curNav.pkgNames[i]]];
+ if (childPkg == null) {
+ return render404();
+ }
+ pkg = childPkg;
+ curNav.pkgObjs.push(pkg);
+ }
+
+ var decl = zigAnalysis.types[pkg.main];
+ curNav.declObjs = [decl];
+ for (var i = 0; i < curNav.declNames.length; i += 1) {
+ var childDecl = findSubDecl(decl, curNav.declNames[i]);
+ if (childDecl == null) {
+ return render404();
+ }
+ var container = getDeclContainerType(childDecl);
+ if (container == null) {
+ if (i + 1 === curNav.declNames.length) {
+ curNav.declObjs.push(childDecl);
+ break;
+ } else {
+ return render404();
+ }
+ }
+ decl = container;
+ curNav.declObjs.push(decl);
+ }
+
+ renderNav();
+
+ var lastDecl = curNav.declObjs[curNav.declObjs.length - 1];
+ if (lastDecl.kind === 'var') {
+ return renderVar(lastDecl);
+ }
+ if (lastDecl.type != null) {
+ var typeObj = zigAnalysis.types[lastDecl.type];
+ if (typeObj.kind === typeKindFnId) {
+ return renderFn(lastDecl);
+ }
+ throw new Error("docs for this decl which is not a container");
+ }
+ renderType(lastDecl);
+ if (lastDecl.pubDecls != null) {
+ renderContainer(lastDecl);
+ }
+ }
+
+ function typeIsErrSet(typeIndex) {
+ var typeObj = zigAnalysis.types[typeIndex];
+ return typeObj.kind === typeKindErrSetId;
+ }
+
+ function typeIsGenericFn(typeIndex) {
+ var typeObj = zigAnalysis.types[typeIndex];
+ if (typeObj.kind !== typeKindFnId) {
+ return false;
+ }
+ return typeObj.generic;
+ }
+
+ function renderFn(fnDecl) {
+ domFnProtoCode.innerHTML = typeIndexName(fnDecl.type, true, true, fnDecl);
+
+ var docsSource = null;
+ var srcNode = zigAnalysis.astNodes[fnDecl.src];
+ if (srcNode.docs != null) {
+ docsSource = srcNode.docs;
+ }
+
+ var typeObj = zigAnalysis.types[fnDecl.type];
+ var errSetTypeIndex = null;
+ if (typeObj.ret != null) {
+ var retType = zigAnalysis.types[typeObj.ret];
+ if (retType.kind === typeKindErrSetId) {
+ errSetTypeIndex = typeObj.ret;
+ } else if (retType.kind === typeKindErrUnionId) {
+ errSetTypeIndex = retType.err;
+ }
+ }
+ if (errSetTypeIndex != null) {
+ var errSetType = zigAnalysis.types[errSetTypeIndex];
+ if (errSetType.errors == null) {
+ domFnErrorsAnyError.classList.remove("hidden");
+ } else {
+ var errorList = [];
+ for (var i = 0; i < errSetType.errors.length; i += 1) {
+ var errObj = zigAnalysis.errors[errSetType.errors[i]];
+ var srcObj = zigAnalysis.astNodes[errObj.src];
+ errorList.push({
+ err: errObj,
+ docs: srcObj.docs,
+ });
+ }
+ errorList.sort(function(a, b) {
+ return operatorCompare(a.err.name.toLowerCase(), b.err.name.toLowerCase());
+ });
+
+ resizeDomList(domListFnErrors, errorList.length, '<tr><td></td><td></td></tr>');
+ for (var i = 0; i < errorList.length; i += 1) {
+ var trDom = domListFnErrors.children[i];
+ var nameTdDom = trDom.children[0];
+ var descTdDom = trDom.children[1];
+ nameTdDom.textContent = errorList[i].err.name;
+ var docs = errorList[i].docs;
+ if (docs != null) {
+ descTdDom.innerHTML = markdown(docs);
+ } else {
+ descTdDom.textContent = "";
+ }
+ }
+ domTableFnErrors.classList.remove("hidden");
+ }
+ domSectFnErrors.classList.remove("hidden");
+ }
+
+ var protoSrcIndex;
+ if (typeIsGenericFn(fnDecl.type)) {
+ protoSrcIndex = fnDecl.value;
+
+ var instantiations = nodesToFnsMap[protoSrcIndex];
+ var calls = nodesToCallsMap[protoSrcIndex];
+ if (instantiations == null && calls == null) {
+ domFnNoExamples.classList.remove("hidden");
+ } else {
+ // TODO show examples
+ domFnExamples.classList.remove("hidden");
+ }
+ } else {
+ protoSrcIndex = zigAnalysis.fns[fnDecl.value].src;
+
+ domFnExamples.classList.add("hidden");
+ domFnNoExamples.classList.add("hidden");
+ }
+
+ var protoSrcNode = zigAnalysis.astNodes[protoSrcIndex];
+ if (docsSource == null && protoSrcNode != null && protoSrcNode.docs != null) {
+ docsSource = protoSrcNode.docs;
+ }
+ if (docsSource != null) {
+ domFnDocs.innerHTML = markdown(docsSource);
+ domFnDocs.classList.remove("hidden");
+ }
+ domFnProto.classList.remove("hidden");
+ }
+
+ function renderNav() {
+ var len = curNav.pkgNames.length + curNav.declNames.length;
+ resizeDomList(domListNav, len, '<li><a href="#"></a></li>');
+ var list = [];
+ var hrefPkgNames = [];
+ var hrefDeclNames = [];
+ for (var i = 0; i < curNav.pkgNames.length; i += 1) {
+ hrefPkgNames.push(curNav.pkgNames[i]);
+ list.push({
+ name: curNav.pkgNames[i],
+ link: navLink(hrefPkgNames, hrefDeclNames),
+ });
+ }
+ for (var i = 0; i < curNav.declNames.length; i += 1) {
+ hrefDeclNames.push(curNav.declNames[i]);
+ list.push({
+ name: curNav.declNames[i],
+ link: navLink(hrefPkgNames, hrefDeclNames),
+ });
+ }
+
+ for (var i = 0; i < list.length; i += 1) {
+ var liDom = domListNav.children[i];
+ var aDom = liDom.children[0];
+ aDom.textContent = list[i].name;
+ aDom.setAttribute('href', list[i].link);
+ if (i + 1 == list.length) {
+ aDom.classList.add("active");
+ } else {
+ aDom.classList.remove("active");
+ }
+ }
+
+ domSectNav.classList.remove("hidden");
+ }
+
+ function renderInfo() {
+ domTdZigVer.textContent = zigAnalysis.params.zigVersion;
+ domTdTarget.textContent = zigAnalysis.params.target;
+
+ domSectInfo.classList.remove("hidden");
+ }
+
+ function render404() {
+ domStatus.textContent = "404 Not Found";
+ domStatus.classList.remove("hidden");
+ }
+
+ function renderPkgList() {
+ var rootPkg = zigAnalysis.packages[zigAnalysis.rootPkg];
+ var list = [];
+ for (var key in rootPkg.table) {
+ if (key === "root" && rootIsStd) continue;
+ var pkgIndex = rootPkg.table[key];
+ if (zigAnalysis.packages[pkgIndex] == null) continue;
+ list.push({
+ name: key,
+ pkg: pkgIndex,
+ });
+ }
+ list.sort(function(a, b) {
+ return operatorCompare(a.name.toLowerCase(), b.name.toLowerCase());
+ });
+
+ if (list.length !== 0) {
+ resizeDomList(domListPkgs, list.length, '<li><a href="#"></a></li>');
+ for (var i = 0; i < list.length; i += 1) {
+ var liDom = domListPkgs.children[i];
+ var aDom = liDom.children[0];
+ aDom.textContent = list[i].name;
+ aDom.setAttribute('href', navLinkPkg(list[i].pkg));
+ if (list[i].name === curNav.pkgNames[0]) {
+ aDom.classList.add("active");
+ } else {
+ aDom.classList.remove("active");
+ }
+ }
+
+ domSectPkgs.classList.remove("hidden");
+ }
+ }
+
+ function navLink(pkgNames, declNames) {
+ if (pkgNames.length === 0 && declNames.length === 0) {
+ return '#';
+ } else if (declNames.length === 0) {
+ return '#' + pkgNames.join('.');
+ } else {
+ return '#' + pkgNames.join('.') + ';' + declNames.join('.');
+ }
+ }
+
+ function navLinkPkg(pkgIndex) {
+ return navLink(canonPkgPaths[pkgIndex], []);
+ }
+
+ function navLinkDecl(childName) {
+ return navLink(curNav.pkgNames, curNav.declNames.concat([childName]));
+ }
+
+ function resizeDomList(listDom, desiredLen, templateHtml) {
+ // add the missing dom entries
+ var i, ev;
+ for (i = listDom.childElementCount; i < desiredLen; i += 1) {
+ listDom.insertAdjacentHTML('beforeend', templateHtml);
+ }
+ // remove extra dom entries
+ while (desiredLen < listDom.childElementCount) {
+ listDom.removeChild(listDom.lastChild);
+ }
+ }
+
+ function typeIndexName(typeIndex, wantHtml, wantLink, fnDecl, skipFnName) {
+ var typeObj = zigAnalysis.types[typeIndex];
+ if (wantLink) {
+ var declIndex = getCanonTypeDecl(typeIndex);
+ var declPath = getCanonDeclPath(declIndex);
+ var haveLink = declPath != null;
+ var typeNameHtml = typeName(typeObj, true, !haveLink, fnDecl, skipFnName);
+ if (haveLink) {
+ return '<a href="' + navLink(declPath.pkgNames, declPath.declNames) + '">' + typeNameHtml + '</a>';
+ } else {
+ return typeNameHtml;
+ }
+ } else {
+ return typeName(typeObj, wantHtml, false, fnDecl, skipFnName);
+ }
+ }
+
+ function typeName(typeObj, wantHtml, wantSubLink, fnDecl, skipFnName) {
+ switch (typeObj.kind) {
+ case typeKindPtrId:
+ var name = "";
+ switch (typeObj.len) {
+ case 0:
+ default:
+ name += "*";
+ break;
+ case 1:
+ name += "[*]";
+ break;
+ case 2:
+ name += "[]";
+ break;
+ case 3:
+ name += "[*c]";
+ break;
+ }
+ if (typeObj['const']) {
+ if (wantHtml) {
+ name += '<span class="tok-kw">const</span> ';
+ } else {
+ name += "const ";
+ }
+ }
+ if (typeObj['volatile']) {
+ if (wantHtml) {
+ name += '<span class="tok-kw">volatile</span> ';
+ } else {
+ name += "volatile ";
+ }
+ }
+ if (typeObj.align != null) {
+ if (wantHtml) {
+ name += '<span class="tok-kw">align</span>(';
+ } else {
+ name += "align(";
+ }
+ if (wantHtml) {
+ name += '<span class="tok-number">' + typeObj.align + '</span>';
+ } else {
+ name += typeObj.align;
+ }
+ if (typeObj.hostIntBytes != null) {
+ name += ":";
+ if (wantHtml) {
+ name += '<span class="tok-number">' + typeObj.bitOffsetInHost + '</span>';
+ } else {
+ name += typeObj.bitOffsetInHost;
+ }
+ name += ":";
+ if (wantHtml) {
+ name += '<span class="tok-number">' + typeObj.hostIntBytes + '</span>';
+ } else {
+ name += typeObj.hostIntBytes;
+ }
+ }
+ name += ") ";
+ }
+ name += typeIndexName(typeObj.elem, wantHtml, wantSubLink, null);
+ return name;
+ case typeKindFloatId:
+ if (wantHtml) {
+ return '<span class="tok-type">f' + typeObj.bits + '</span>';
+ } else {
+ return "f" + typeObj.bits;
+ }
+ case typeKindIntId:
+ var signed = (typeObj.i != null) ? 'i' : 'u';
+ var bits = typeObj[signed];
+ if (wantHtml) {
+ return '<span class="tok-type">' + signed + bits + '</span>';
+ } else {
+ return signed + bits;
+ }
+ case typeKindTypeId:
+ if (wantHtml) {
+ return '<span class="tok-type">type</span>';
+ } else {
+ return "type";
+ }
+ case typeKindBoolId:
+ if (wantHtml) {
+ return '<span class="tok-type">bool</span>';
+ } else {
+ return "bool";
+ }
+ case typeKindVoidId:
+ if (wantHtml) {
+ return '<span class="tok-type">void</span>';
+ } else {
+ return "void";
+ }
+ case typeKindErrSetId:
+ if (typeObj.errors == null) {
+ if (wantHtml) {
+ return '<span class="tok-type">anyerror</span>';
+ } else {
+ return "anyerror";
+ }
+ } else {
+ if (wantHtml) {
+ return escapeHtml(typeObj.name);
+ } else {
+ return typeObj.name;
+ }
+ }
+ case typeKindErrUnionId:
+ var errSetTypeObj = zigAnalysis.types[typeObj.err];
+ var payloadHtml = typeIndexName(typeObj.payload, wantHtml, wantSubLink, null);
+ if (fnDecl != null && errSetTypeObj.fn === fnDecl.value) {
+ // function index parameter supplied and this is the inferred error set of it
+ return "!" + payloadHtml;
+ } else {
+ return typeIndexName(typeObj.err, wantHtml, wantSubLink, null) + "!" + payloadHtml;
+ }
+ case typeKindFnId:
+ var payloadHtml = "";
+ if (wantHtml) {
+ payloadHtml += '<span class="tok-kw">fn</span>';
+ if (fnDecl != null && !skipFnName) {
+ payloadHtml += ' <span class="tok-fn">' + escapeHtml(fnDecl.name) + '</span>';
+ }
+ } else {
+ payloadHtml += 'fn'
+ }
+ payloadHtml += '(';
+ if (typeObj.args != null) {
+ for (var i = 0; i < typeObj.args.length; i += 1) {
+ if (i != 0) {
+ payloadHtml += ', ';
+ }
+ var argTypeIndex = typeObj.args[i];
+ if (argTypeIndex != null) {
+ payloadHtml += typeIndexName(argTypeIndex, wantHtml, wantSubLink);
+ } else if (wantHtml) {
+ payloadHtml += '<span class="tok-kw">var</span>';
+ } else {
+ payloadHtml += 'var';
+ }
+ }
+ }
+
+ payloadHtml += ') ';
+ if (typeObj.ret != null) {
+ payloadHtml += typeIndexName(typeObj.ret, wantHtml, wantSubLink, fnDecl);
+ } else if (wantHtml) {
+ payloadHtml += '<span class="tok-kw">var</span>';
+ } else {
+ payloadHtml += 'var';
+ }
+ return payloadHtml;
+ default:
+ if (wantHtml) {
+ return escapeHtml(typeObj.name);
+ } else {
+ return typeObj.name;
+ }
+ }
+ }
+
+ function renderType(typeObj) {
+ var name = typeName(typeObj, false, false);
+ if (name != null && name != "") {
+ domHdrName.innerText = zigAnalysis.typeKinds[typeObj.kind] + " " + name;
+ domHdrName.classList.remove("hidden");
+ }
+ }
+
+ function allCompTimeFnCallsHaveTypeResult(typeIndex, value) {
+ var srcIndex = typeIsGenericFn(typeIndex) ? value : zigAnalysis.fns[value].src;
+ var calls = nodesToCallsMap[srcIndex];
+ if (calls == null) return false;
+ for (var i = 0; i < calls.length; i += 1) {
+ var call = zigAnalysis.calls[calls[i]];
+ if (call.result.type !== typeTypeId) return false;
+ }
+ return true;
+ }
+
+ function renderVar(decl) {
+ domFnProtoCode.innerHTML = '<span class="tok-kw">pub</span> <span class="tok-kw">var</span> ' +
+ escapeHtml(decl.name) + ': ' + typeIndexName(decl.type, true, true);
+
+ var docs = zigAnalysis.astNodes[decl.src].docs;
+ if (docs != null) {
+ domFnDocs.innerHTML = markdown(docs);
+ domFnDocs.classList.remove("hidden");
+ }
+
+ domFnProto.classList.remove("hidden");
+ }
+
+ function renderContainer(container) {
+ var typesList = [];
+ var errSetsList = [];
+ var fnsList = [];
+ var varsList = [];
+ for (var i = 0; i < container.pubDecls.length; i += 1) {
+ var decl = zigAnalysis.decls[container.pubDecls[i]];
+ if (decl.kind === 'var') {
+ varsList.push(decl);
+ continue;
+ }
+ if (decl.type != null) {
+ if (decl.type == typeTypeId) {
+ if (typeIsErrSet(decl.value)) {
+ errSetsList.push(decl);
+ } else {
+ typesList.push(decl);
+ }
+ } else {
+ var typeKind = zigAnalysis.types[decl.type].kind;
+ if (typeKind === typeKindFnId) {
+ if (allCompTimeFnCallsHaveTypeResult(decl.type, decl.value)) {
+ typesList.push(decl);
+ } else {
+ fnsList.push(decl);
+ }
+ }
+ }
+ }
+ }
+ typesList.sort(function(a, b) {
+ return operatorCompare(a.name, b.name);
+ });
+ errSetsList.sort(function(a, b) {
+ return operatorCompare(a.name, b.name);
+ });
+ fnsList.sort(function(a, b) {
+ return operatorCompare(a.name, b.name);
+ });
+ varsList.sort(function(a, b) {
+ return operatorCompare(a.name, b.name);
+ });
+
+ if (typesList.length !== 0) {
+ resizeDomList(domListTypes, typesList.length, '<li><a href="#"></a></li>');
+ for (var i = 0; i < typesList.length; i += 1) {
+ var liDom = domListTypes.children[i];
+ var aDom = liDom.children[0];
+ var decl = typesList[i];
+ aDom.textContent = decl.name;
+ aDom.setAttribute('href', navLinkDecl(decl.name));
+ }
+ domSectTypes.classList.remove("hidden");
+ }
+
+ if (errSetsList.length !== 0) {
+ resizeDomList(domListErrSets, errSetsList.length, '<li><a href="#"></a></li>');
+ for (var i = 0; i < errSetsList.length; i += 1) {
+ var liDom = domListErrSets.children[i];
+ var aDom = liDom.children[0];
+ var decl = errSetsList[i];
+ aDom.textContent = decl.name;
+ aDom.setAttribute('href', navLinkDecl(decl.name));
+ }
+ domSectErrSets.classList.remove("hidden");
+ }
+
+ if (fnsList.length !== 0) {
+ resizeDomList(domListFns, fnsList.length,
+ '<tr><td><a href="#"></a></td><td></td><td></td></tr>');
+ for (var i = 0; i < fnsList.length; i += 1) {
+ var decl = fnsList[i];
+ var trDom = domListFns.children[i];
+
+ var tdName = trDom.children[0];
+ var tdNameA = tdName.children[0];
+ var tdType = trDom.children[1];
+ var tdDesc = trDom.children[2];
+
+ tdNameA.setAttribute('href', navLinkDecl(decl.name));
+ tdNameA.textContent = decl.name;
+
+ tdType.innerHTML = typeIndexName(decl.type, true, true, decl, true);
+
+ var docs = zigAnalysis.astNodes[decl.src].docs;
+ if (docs != null) {
+ tdDesc.innerHTML = shortDescMarkdown(docs);
+ } else {
+ tdDesc.textContent = "";
+ }
+ }
+ domSectFns.classList.remove("hidden");
+ }
+
+ if (container.fields.length !== 0) {
+ resizeDomList(domListFields, container.fields.length, '<li></li>');
+ for (var i = 0; i < container.fields.length; i += 1) {
+ var liDom = domListFields.children[i];
+ var field = container.fields[i];
+
+ var protoHtml = escapeHtml(field.name) + ": ";
+ protoHtml += typeIndexName(field.type, true, true);
+ liDom.innerHTML = protoHtml;
+ }
+ domSectFields.classList.remove("hidden");
+ }
+
+ if (varsList.length !== 0) {
+ resizeDomList(domListGlobalVars, varsList.length,
+ '<tr><td><a href="#"></a></td><td></td><td></td></tr>');
+ for (var i = 0; i < varsList.length; i += 1) {
+ var decl = varsList[i];
+ var trDom = domListGlobalVars.children[i];
+
+ var tdName = trDom.children[0];
+ var tdNameA = tdName.children[0];
+ var tdType = trDom.children[1];
+ var tdDesc = trDom.children[2];
+
+ tdNameA.setAttribute('href', navLinkDecl(decl.name));
+ tdNameA.textContent = decl.name;
+
+ tdType.innerHTML = typeIndexName(decl.type, true, true);
+
+ var docs = zigAnalysis.astNodes[decl.src].docs;
+ if (docs != null) {
+ tdDesc.innerHTML = shortDescMarkdown(docs);
+ } else {
+ tdDesc.textContent = "";
+ }
+ }
+ domSectGlobalVars.classList.remove("hidden");
+ }
+ }
+
+ function operatorCompare(a, b) {
+ if (a === b) {
+ return 0;
+ } else if (a < b) {
+ return -1;
+ } else {
+ return 1;
+ }
+ }
+
+ function detectRootIsStd() {
+ var rootPkg = zigAnalysis.packages[zigAnalysis.rootPkg];
+ if (rootPkg.table["std"] == null) {
+ // no std mapped into the root package
+ return false;
+ }
+ var stdPkg = zigAnalysis.packages[rootPkg.table["std"]];
+ if (stdPkg == null) return false;
+ return rootPkg.file === stdPkg.file;
+ }
+
+ function findTypeKinds() {
+ for (var i = 0; i < zigAnalysis.typeKinds.length; i += 1) {
+ if (zigAnalysis.typeKinds[i] === "Type") {
+ typeKindTypeId = i;
+ } else if (zigAnalysis.typeKinds[i] === "Fn") {
+ typeKindFnId = i;
+ } else if (zigAnalysis.typeKinds[i] === "Pointer") {
+ typeKindPtrId = i;
+ } else if (zigAnalysis.typeKinds[i] === "Float") {
+ typeKindFloatId = i;
+ } else if (zigAnalysis.typeKinds[i] === "Int") {
+ typeKindIntId = i;
+ } else if (zigAnalysis.typeKinds[i] === "Bool") {
+ typeKindBoolId = i;
+ } else if (zigAnalysis.typeKinds[i] === "Void") {
+ typeKindVoidId = i;
+ } else if (zigAnalysis.typeKinds[i] === "ErrorSet") {
+ typeKindErrSetId = i;
+ } else if (zigAnalysis.typeKinds[i] === "ErrorUnion") {
+ typeKindErrUnionId = i;
+ }
+ }
+ if (typeKindTypeId == null) {
+ throw new Error("No type kind 'Type' found");
+ }
+ if (typeKindFnId == null) {
+ throw new Error("No type kind 'Fn' found");
+ }
+ if (typeKindPtrId == null) {
+ throw new Error("No type kind 'Pointer' found");
+ }
+ if (typeKindFloatId == null) {
+ throw new Error("No type kind 'Float' found");
+ }
+ if (typeKindIntId == null) {
+ throw new Error("No type kind 'Int' found");
+ }
+ if (typeKindBoolId == null) {
+ throw new Error("No type kind 'Bool' found");
+ }
+ if (typeKindVoidId == null) {
+ throw new Error("No type kind 'Void' found");
+ }
+ if (typeKindErrSetId == null) {
+ throw new Error("No type kind 'ErrorSet' found");
+ }
+ if (typeKindErrUnionId == null) {
+ throw new Error("No type kind 'ErrorUnion' found");
+ }
+ }
+
+ function findTypeTypeId() {
+ for (var i = 0; i < zigAnalysis.types.length; i += 1) {
+ if (zigAnalysis.types[i].kind == typeKindTypeId) {
+ return i;
+ }
+ }
+ throw new Error("No type 'type' found");
+ }
+
+ function onHashChange() {
+ curNav = {
+ pkgNames: [],
+ pkgObjs: [],
+ declNames: [],
+ declObjs: [],
+ };
+ curNavSearch = "";
+
+ if (location.hash[0] === '#' && location.hash.length > 1) {
+ var query = location.hash.substring(1);
+ var qpos = query.indexOf("?");
+ if (qpos === -1) {
+ nonSearchPart = query;
+ } else {
+ nonSearchPart = query.substring(0, qpos);
+ curNavSearch = decodeURIComponent(query.substring(qpos + 1));
+ }
+
+ var parts = nonSearchPart.split(";");
+ curNav.pkgNames = decodeURIComponent(parts[0]).split(".");
+ if (parts[1] != null) {
+ curNav.declNames = decodeURIComponent(parts[1]).split(".");
+ }
+ }
+ if (domSearch.value !== curNavSearch) {
+ domSearch.value = curNavSearch;
+ }
+ render();
+ }
+
+ function findSubDecl(parentType, childName) {
+ if (parentType.pubDecls == null) throw new Error("parent object has no public decls");
+ for (var i = 0; i < parentType.pubDecls.length; i += 1) {
+ var declIndex = parentType.pubDecls[i];
+ var childDecl = zigAnalysis.decls[declIndex];
+ if (childDecl.name === childName) {
+ return childDecl;
+ }
+ }
+ return null;
+ }
+
+ function getDeclContainerType(decl) {
+ if (decl.type === typeTypeId) {
+ return zigAnalysis.types[decl.value];
+ }
+ return null;
+ }
+
+ function computeCanonicalPackagePaths() {
+ var list = new Array(zigAnalysis.packages.length);
+ // Now we try to find all the packages from root.
+ var rootPkg = zigAnalysis.packages[zigAnalysis.rootPkg];
+ // Breadth-first to keep the path shortest possible.
+ var stack = [{
+ path: [],
+ pkg: rootPkg,
+ }];
+ while (stack.length !== 0) {
+ var item = stack.shift();
+ for (var key in item.pkg.table) {
+ var childPkgIndex = item.pkg.table[key];
+ if (list[childPkgIndex] != null) continue;
+ var childPkg = zigAnalysis.packages[childPkgIndex];
+ if (childPkg == null) continue;
+
+ var newPath = item.path.concat([key])
+ list[childPkgIndex] = newPath;
+ stack.push({
+ path: newPath,
+ pkg: childPkg,
+ });
+ }
+ }
+ return list;
+ }
+
+ function computeCanonDeclPaths() {
+ var list = new Array(zigAnalysis.decls.length);
+ canonTypeDecls = new Array(zigAnalysis.types.length);
+
+ for (var pkgI = 0; pkgI < zigAnalysis.packages.length; pkgI += 1) {
+ if (pkgI === zigAnalysis.rootPkg && rootIsStd) continue;
+ var pkg = zigAnalysis.packages[pkgI];
+ var pkgNames = canonPkgPaths[pkgI];
+ var stack = [{
+ declNames: [],
+ type: zigAnalysis.types[pkg.main],
+ }];
+ while (stack.length !== 0) {
+ var item = stack.shift();
+
+ if (item.type.pubDecls != null) {
+ for (var declI = 0; declI < item.type.pubDecls.length; declI += 1) {
+ var mainDeclIndex = item.type.pubDecls[declI];
+ if (list[mainDeclIndex] != null) continue;
+
+ var decl = zigAnalysis.decls[mainDeclIndex];
+ if (decl.type === typeTypeId) {
+ canonTypeDecls[decl.value] = mainDeclIndex;
+ }
+ var declNames = item.declNames.concat([decl.name]);
+ list[mainDeclIndex] = {
+ pkgNames: pkgNames,
+ declNames: declNames,
+ };
+ var containerType = getDeclContainerType(decl);
+ if (containerType != null) {
+ stack.push({
+ declNames: declNames,
+ type: containerType,
+ });
+ }
+ }
+ }
+ }
+ }
+ return list;
+ }
+
+ function getCanonDeclPath(index) {
+ if (canonDeclPaths == null) {
+ canonDeclPaths = computeCanonDeclPaths();
+ }
+ return canonDeclPaths[index];
+ }
+
+ function getCanonTypeDecl(index) {
+ getCanonDeclPath(0);
+ return canonTypeDecls[index];
+ }
+
+ function escapeHtml(text) {
+ return text.replace(/[&"<>]/g, function (m) {
+ return escapeHtmlReplacements[m];
+ });
+ }
+
+ function shortDescMarkdown(docs) {
+ var parts = docs.trim().split("\n");
+ var firstLine = parts[0];
+ return markdown(firstLine);
+ }
+
+ function markdown(mdText) {
+ // TODO implement more
+ return escapeHtml(mdText);
+ }
+
+ function onSearchKeyDown(ev) {
+ switch (ev.which) {
+ case 13:
+ var liDom = domListSearchResults.children[curSearchIndex];
+ if (liDom == null && domListSearchResults.children.length !== 0) {
+ liDom = domListSearchResults.children[0];
+ }
+ if (liDom != null) {
+ var aDom = liDom.children[0];
+ location.href = aDom.getAttribute("href");
+ curSearchIndex = -1;
+ ev.preventDefault();
+ ev.stopPropagation();
+ return;
+ }
+ case 27:
+ domSearch.value = "";
+ domSearch.blur();
+ curSearchIndex = -1;
+ ev.preventDefault();
+ ev.stopPropagation();
+ startSearch();
+ return;
+ case 38:
+ moveSearchCursor(-1);
+ ev.preventDefault();
+ ev.stopPropagation();
+ return;
+ case 40:
+ moveSearchCursor(1);
+ ev.preventDefault();
+ ev.stopPropagation();
+ return;
+ default:
+ curSearchIndex = -1;
+ ev.stopPropagation();
+ startAsyncSearch();
+ }
+ }
+
+ function moveSearchCursor(dir) {
+ if (curSearchIndex < 0 || curSearchIndex >= domListSearchResults.children.length) {
+ if (dir > 0) {
+ curSearchIndex = -1 + dir;
+ } else if (dir < 0) {
+ curSearchIndex = domListSearchResults.children.length + dir;
+ }
+ } else {
+ curSearchIndex += dir;
+ }
+ if (curSearchIndex < 0) {
+ curSearchIndex = 0;
+ }
+ if (curSearchIndex >= domListSearchResults.children.length) {
+ curSearchIndex = domListSearchResults.children.length - 1;
+ }
+ renderSearchCursor();
+ }
+
+ function onWindowKeyDown(ev) {
+ switch (ev.which) {
+ case 27:
+ if (!domHelpModal.classList.contains("hidden")) {
+ domHelpModal.classList.add("hidden");
+ ev.preventDefault();
+ ev.stopPropagation();
+ }
+ break;
+ case 83:
+ domSearch.focus();
+ domSearch.select();
+ ev.preventDefault();
+ ev.stopPropagation();
+ startAsyncSearch();
+ break;
+ case 191:
+ ev.preventDefault();
+ ev.stopPropagation();
+ showHelpModal();
+ break;
+ }
+ }
+
+ function showHelpModal() {
+ domHelpModal.classList.remove("hidden");
+ domHelpModal.style.left = (window.innerWidth / 2 - domHelpModal.clientWidth / 2) + "px";
+ domHelpModal.style.top = (window.innerHeight / 2 - domHelpModal.clientHeight / 2) + "px";
+ domHelpModal.focus();
+ }
+
+ function clearAsyncSearch() {
+ if (searchTimer != null) clearTimeout(searchTimer);
+ }
+
+ function startAsyncSearch() {
+ clearAsyncSearch();
+ searchTimer = setTimeout(startSearch, 100);
+ }
+ function startSearch() {
+ var parts = location.hash.split("?");
+ var newPart2 = (domSearch.value === "") ? "" : ("?" + domSearch.value);
+ if (parts.length === 1) {
+ location.hash = location.hash + newPart2;
+ } else {
+ location.hash = parts[0] + newPart2;
+ }
+ }
+ function renderSearch() {
+ var matchedItems = [];
+ var ignoreCase = (curNavSearch.toLowerCase() === curNavSearch);
+ var terms = curNavSearch.split(/[ \r\n\t]+/);
+
+ decl_loop: for (var declIndex = 0; declIndex < zigAnalysis.decls.length; declIndex += 1) {
+ var canonPath = getCanonDeclPath(declIndex);
+ if (canonPath == null) continue;
+
+ var decl = zigAnalysis.decls[declIndex];
+ var lastPkgName = canonPath.pkgNames[canonPath.pkgNames.length - 1];
+ var fullPathSearchText = lastPkgName + "." + canonPath.declNames.join('.');
+ var astNode = zigAnalysis.astNodes[decl.src];
+ var fileAndDocs = zigAnalysis.files[astNode.file];
+ if (astNode.docs != null) {
+ fileAndDocs += "\n" + astNode.docs;
+ }
+ var fullPathSearchTextLower = fullPathSearchText;
+ if (ignoreCase) {
+ fullPathSearchTextLower = fullPathSearchTextLower.toLowerCase();
+ fileAndDocs = fileAndDocs.toLowerCase();
+ }
+
+ var points = 0;
+ for (var termIndex = 0; termIndex < terms.length; termIndex += 1) {
+ var term = terms[termIndex];
+
+ // exact, case sensitive match of full decl path
+ if (fullPathSearchText === term) {
+ points += 4;
+ continue;
+ }
+ // exact, case sensitive match of just decl name
+ if (decl.name == term) {
+ points += 3;
+ continue;
+ }
+ // substring, case insensitive match of full decl path
+ if (fullPathSearchTextLower.indexOf(term) >= 0) {
+ points += 2;
+ continue;
+ }
+ if (fileAndDocs.indexOf(term) >= 0) {
+ points += 1;
+ continue;
+ }
+
+ continue decl_loop;
+ }
+
+ matchedItems.push({
+ decl: decl,
+ path: canonPath,
+ points: points,
+ });
+ }
+
+ if (matchedItems.length !== 0) {
+ resizeDomList(domListSearchResults, matchedItems.length, '<li><a href="#"></a></li>');
+
+ matchedItems.sort(function(a, b) {
+ var cmp = operatorCompare(b.points, a.points);
+ if (cmp != 0) return cmp;
+ return operatorCompare(a.decl.name, b.decl.name);
+ });
+
+ for (var i = 0; i < matchedItems.length; i += 1) {
+ var liDom = domListSearchResults.children[i];
+ var aDom = liDom.children[0];
+ var match = matchedItems[i];
+ var lastPkgName = match.path.pkgNames[match.path.pkgNames.length - 1];
+ aDom.textContent = lastPkgName + "." + match.path.declNames.join('.');
+ aDom.setAttribute('href', navLink(match.path.pkgNames, match.path.declNames));
+ }
+ renderSearchCursor();
+
+ domSectSearchResults.classList.remove("hidden");
+ } else {
+ domSectSearchNoResults.classList.remove("hidden");
+ }
+ }
+
+ function renderSearchCursor() {
+ for (var i = 0; i < domListSearchResults.children.length; i += 1) {
+ var liDom = domListSearchResults.children[i];
+ if (curSearchIndex === i) {
+ liDom.classList.add("selected");
+ } else {
+ liDom.classList.remove("selected");
+ }
+ }
+ }
+
+ function indexNodesToFns() {
+ var map = {};
+ for (var i = 0; i < zigAnalysis.fns.length; i += 1) {
+ var fn = zigAnalysis.fns[i];
+ if (typeIsGenericFn(fn.type)) continue;
+ if (map[fn.src] == null) {
+ map[fn.src] = [i];
+ } else {
+ map[fn.src].push(i);
+ }
+ }
+ return map;
+ }
+
+ function indexNodesToCalls() {
+ var map = {};
+ for (var i = 0; i < zigAnalysis.calls.length; i += 1) {
+ var call = zigAnalysis.calls[i];
+ var fn = zigAnalysis.fns[call.fn];
+ if (map[fn.src] == null) {
+ map[fn.src] = [i];
+ } else {
+ map[fn.src].push(i);
+ }
+ }
+ return map;
+ }
+})();
diff --git a/lib/std/special/start_windows_tls.zig b/lib/std/special/start_windows_tls.zig
index 71165d355b..bfd0e44122 100644
--- a/lib/std/special/start_windows_tls.zig
+++ b/lib/std/special/start_windows_tls.zig
@@ -1,4 +1,5 @@
const std = @import("std");
+const builtin = @import("builtin");
export var _tls_index: u32 = std.os.windows.TLS_OUT_OF_INDEXES;
export var _tls_start: u8 linksection(".tls") = 0;
@@ -6,6 +7,17 @@ export var _tls_end: u8 linksection(".tls$ZZZ") = 0;
export var __xl_a: std.os.windows.PIMAGE_TLS_CALLBACK linksection(".CRT$XLA") = null;
export var __xl_z: std.os.windows.PIMAGE_TLS_CALLBACK linksection(".CRT$XLZ") = null;
+comptime {
+ if (builtin.arch == .i386) {
+ // The __tls_array is the offset of the ThreadLocalStoragePointer field
+ // in the TEB block whose base address held in the %fs segment.
+ asm (
+ \\ .global __tls_array
+ \\ __tls_array = 0x2C
+ );
+ }
+}
+
// TODO this is how I would like it to be expressed
// TODO also note, ReactOS has a +1 on StartAddressOfRawData and AddressOfCallBacks. Investigate
// why they do that.
diff --git a/lib/std/std.zig b/lib/std/std.zig
index 1c64242c4b..3c5655e8f3 100644
--- a/lib/std/std.zig
+++ b/lib/std/std.zig
@@ -62,61 +62,69 @@ pub const unicode = @import("unicode.zig");
pub const valgrind = @import("valgrind.zig");
pub const zig = @import("zig.zig");
-test "std" {
- // run tests from these
- _ = @import("array_list.zig");
- _ = @import("atomic.zig");
- _ = @import("bloom_filter.zig");
- _ = @import("buf_map.zig");
- _ = @import("buf_set.zig");
- _ = @import("buffer.zig");
- _ = @import("hash_map.zig");
- _ = @import("linked_list.zig");
- _ = @import("mutex.zig");
- _ = @import("statically_initialized_mutex.zig");
- _ = @import("segmented_list.zig");
- _ = @import("spinlock.zig");
- _ = @import("child_process.zig");
+// Reference everything so it gets tested.
+test "" {
+ _ = AlignedArrayList;
+ _ = ArrayList;
+ _ = AutoHashMap;
+ _ = BloomFilter;
+ _ = BufMap;
+ _ = BufSet;
+ _ = Buffer;
+ _ = BufferOutStream;
+ _ = DynLib;
+ _ = HashMap;
+ _ = Mutex;
+ _ = PackedIntArrayEndian;
+ _ = PackedIntArray;
+ _ = PackedIntSliceEndian;
+ _ = PackedIntSlice;
+ _ = PriorityQueue;
+ _ = SinglyLinkedList;
+ _ = StaticallyInitializedMutex;
+ _ = SegmentedList;
+ _ = SpinLock;
+ _ = StringHashMap;
+ _ = ChildProcess;
+ _ = TailQueue;
+ _ = Thread;
- _ = @import("ascii.zig");
- _ = @import("base64.zig");
- _ = @import("build.zig");
- _ = @import("c.zig");
- _ = @import("coff.zig");
- _ = @import("crypto.zig");
- _ = @import("cstr.zig");
- _ = @import("debug.zig");
- _ = @import("dwarf.zig");
- _ = @import("dynamic_library.zig");
- _ = @import("elf.zig");
- _ = @import("event.zig");
- _ = @import("fmt.zig");
- _ = @import("fs.zig");
- _ = @import("hash.zig");
- _ = @import("heap.zig");
- _ = @import("http.zig");
- _ = @import("io.zig");
- _ = @import("json.zig");
- _ = @import("lazy_init.zig");
- _ = @import("macho.zig");
- _ = @import("math.zig");
- _ = @import("mem.zig");
- _ = @import("meta.zig");
- _ = @import("net.zig");
- _ = @import("os.zig");
- _ = @import("pdb.zig");
- _ = @import("process.zig");
- _ = @import("packed_int_array.zig");
- _ = @import("priority_queue.zig");
- _ = @import("rand.zig");
- _ = @import("rb.zig");
- _ = @import("sort.zig");
- _ = @import("testing.zig");
- _ = @import("thread.zig");
- _ = @import("time.zig");
- _ = @import("unicode.zig");
- _ = @import("valgrind.zig");
- _ = @import("zig.zig");
-
- _ = @import("debug/leb128.zig");
+ _ = atomic;
+ _ = base64;
+ _ = build;
+ _ = c;
+ _ = coff;
+ _ = crypto;
+ _ = cstr;
+ _ = debug;
+ _ = dwarf;
+ _ = elf;
+ _ = event;
+ _ = fmt;
+ _ = fs;
+ _ = hash;
+ _ = hash_map;
+ _ = heap;
+ _ = http;
+ _ = io;
+ _ = json;
+ _ = lazyInit;
+ _ = macho;
+ _ = math;
+ _ = mem;
+ _ = meta;
+ _ = net;
+ _ = os;
+ _ = packed_int_array;
+ _ = pdb;
+ _ = process;
+ _ = rand;
+ _ = rb;
+ _ = sort;
+ _ = ascii;
+ _ = testing;
+ _ = time;
+ _ = unicode;
+ _ = valgrind;
+ _ = zig;
}
diff --git a/src/all_types.hpp b/src/all_types.hpp
index 1119d2bf4e..c9f905118f 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -589,6 +589,7 @@ enum NodeType {
NodeTypeIfErrorExpr,
NodeTypeIfOptional,
NodeTypeErrorSetDecl,
+ NodeTypeErrorSetField,
NodeTypeResume,
NodeTypeAwaitExpr,
NodeTypeSuspend,
@@ -612,16 +613,10 @@ enum FnInline {
};
struct AstNodeFnProto {
- VisibMod visib_mod;
Buf *name;
ZigList<AstNode *> params;
AstNode *return_type;
Token *return_var_token;
- bool is_var_args;
- bool is_extern;
- bool is_export;
- FnInline fn_inline;
- CallingConvention cc;
AstNode *fn_def_node;
// populated if this is an extern declaration
Buf *lib_name;
@@ -629,8 +624,16 @@ struct AstNodeFnProto {
AstNode *align_expr;
// populated if the "section(S)" is present
AstNode *section_expr;
+ Buf doc_comments;
+ FnInline fn_inline;
+ CallingConvention cc;
+
+ VisibMod visib_mod;
bool auto_err_set;
+ bool is_var_args;
+ bool is_extern;
+ bool is_export;
};
struct AstNodeFnDef {
@@ -642,6 +645,7 @@ struct AstNodeParamDecl {
Buf *name;
AstNode *type;
Token *var_token;
+ Buf doc_comments;
bool is_noalias;
bool is_comptime;
bool is_var_args;
@@ -684,6 +688,7 @@ struct AstNodeVariableDeclaration {
// populated if the "section(S)" is present
AstNode *section_expr;
Token *threadlocal_tok;
+ Buf doc_comments;
VisibMod visib_mod;
bool is_const;
@@ -957,25 +962,35 @@ enum ContainerLayout {
};
struct AstNodeContainerDecl {
- ContainerKind kind;
+ AstNode *init_arg_expr; // enum(T), struct(endianness), or union(T), or union(enum(T))
ZigList<AstNode *> fields;
ZigList<AstNode *> decls;
+
+ ContainerKind kind;
ContainerLayout layout;
- AstNode *init_arg_expr; // enum(T), struct(endianness), or union(T), or union(enum(T))
+
bool auto_enum, is_root; // union(enum)
};
+struct AstNodeErrorSetField {
+ Buf doc_comments;
+ AstNode *field_name;
+};
+
struct AstNodeErrorSetDecl {
+ // Each AstNode could be AstNodeErrorSetField or just AstNodeSymbolExpr to save memory
ZigList<AstNode *> decls;
};
struct AstNodeStructField {
- VisibMod visib_mod;
Buf *name;
AstNode *type;
AstNode *value;
// populated if the "align(A)" is present
AstNode *align_expr;
+ Buf doc_comments;
+
+ VisibMod visib_mod;
};
struct AstNodeStringLiteral {
@@ -1126,6 +1141,7 @@ struct AstNode {
AstNodeInferredArrayType inferred_array_type;
AstNodeErrorType error_type;
AstNodeErrorSetDecl err_set_decl;
+ AstNodeErrorSetField err_set_field;
AstNodeResumeExpr resume_expr;
AstNodeAwaitExpr await_expr;
AstNodeSuspend suspend;
@@ -1274,9 +1290,10 @@ struct ZigTypeErrorUnion {
};
struct ZigTypeErrorSet {
- uint32_t err_count;
ErrorTableEntry **errors;
ZigFn *infer_fn;
+ uint32_t err_count;
+ bool incomplete;
};
struct ZigTypeEnum {
@@ -1306,6 +1323,15 @@ bool pkg_ptr_eql(const ZigPackage *a, const ZigPackage *b);
uint32_t tld_ptr_hash(const Tld *ptr);
bool tld_ptr_eql(const Tld *a, const Tld *b);
+uint32_t node_ptr_hash(const AstNode *ptr);
+bool node_ptr_eql(const AstNode *a, const AstNode *b);
+
+uint32_t fn_ptr_hash(const ZigFn *ptr);
+bool fn_ptr_eql(const ZigFn *a, const ZigFn *b);
+
+uint32_t err_ptr_hash(const ErrorTableEntry *ptr);
+bool err_ptr_eql(const ErrorTableEntry *a, const ErrorTableEntry *b);
+
struct ZigTypeUnion {
AstNode *decl_node;
TypeUnionField *fields;
@@ -2120,6 +2146,7 @@ struct ErrorTableEntry {
Buf name;
uint32_t value;
AstNode *decl_node;
+ ErrorTableEntry *other; // null, or another error decl that was merged into this
ZigType *set_with_only_this_in_it;
// If we generate a constant error name value for this error, we memoize it here.
// The type of this is array
diff --git a/src/analyze.cpp b/src/analyze.cpp
index cca239c275..82b09175d3 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -913,7 +913,10 @@ bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id) {
if (type_is_c_abi_int(g, fn_type_id->return_type)) {
return false;
}
- if (g->zig_target->arch == ZigLLVM_x86_64) {
+ if (g->zig_target->arch == ZigLLVM_x86) {
+ X64CABIClass abi_class = type_c_abi_x86_64_class(g, fn_type_id->return_type);
+ return abi_class == X64CABIClass_MEMORY;
+ } else if (g->zig_target->arch == ZigLLVM_x86_64) {
X64CABIClass abi_class = type_c_abi_x86_64_class(g, fn_type_id->return_type);
return abi_class == X64CABIClass_MEMORY;
} else if (target_is_arm(g->zig_target) || target_is_riscv(g->zig_target)) {
@@ -1633,6 +1636,7 @@ ZigType *get_auto_err_set_type(CodeGen *g, ZigFn *fn_entry) {
err_set_type->data.error_set.err_count = 0;
err_set_type->data.error_set.errors = nullptr;
err_set_type->data.error_set.infer_fn = fn_entry;
+ err_set_type->data.error_set.incomplete = true;
err_set_type->size_in_bits = g->builtin_types.entry_global_error_set->size_in_bits;
err_set_type->abi_align = g->builtin_types.entry_global_error_set->abi_align;
err_set_type->abi_size = g->builtin_types.entry_global_error_set->abi_size;
@@ -3572,6 +3576,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
case NodeTypeSuspend:
case NodeTypeEnumLiteral:
case NodeTypeAnyFrameType:
+ case NodeTypeErrorSetField:
zig_unreachable();
}
}
@@ -4276,12 +4281,12 @@ static void define_local_param_variables(CodeGen *g, ZigFn *fn_table_entry) {
bool resolve_inferred_error_set(CodeGen *g, ZigType *err_set_type, AstNode *source_node) {
assert(err_set_type->id == ZigTypeIdErrorSet);
ZigFn *infer_fn = err_set_type->data.error_set.infer_fn;
- if (infer_fn != nullptr) {
+ if (infer_fn != nullptr && err_set_type->data.error_set.incomplete) {
if (infer_fn->anal_state == FnAnalStateInvalid) {
return false;
} else if (infer_fn->anal_state == FnAnalStateReady) {
analyze_fn_body(g, infer_fn);
- if (err_set_type->data.error_set.infer_fn != nullptr) {
+ if (err_set_type->data.error_set.incomplete) {
assert(g->errors.length != 0);
return false;
}
@@ -4508,7 +4513,9 @@ static void analyze_fn_ir(CodeGen *g, ZigFn *fn, AstNode *return_type_node) {
if (fn_type_id->return_type->id == ZigTypeIdErrorUnion) {
ZigType *return_err_set_type = fn_type_id->return_type->data.error_union.err_set_type;
- if (return_err_set_type->data.error_set.infer_fn != nullptr) {
+ if (return_err_set_type->data.error_set.infer_fn != nullptr &&
+ return_err_set_type->data.error_set.incomplete)
+ {
ZigType *inferred_err_set_type;
if (fn->src_implicit_return_type->id == ZigTypeIdErrorSet) {
inferred_err_set_type = fn->src_implicit_return_type;
@@ -4521,14 +4528,16 @@ static void analyze_fn_ir(CodeGen *g, ZigFn *fn, AstNode *return_type_node) {
return;
}
- if (inferred_err_set_type->data.error_set.infer_fn != nullptr) {
+ if (inferred_err_set_type->data.error_set.infer_fn != nullptr &&
+ inferred_err_set_type->data.error_set.incomplete)
+ {
if (!resolve_inferred_error_set(g, inferred_err_set_type, return_type_node)) {
fn->anal_state = FnAnalStateInvalid;
return;
}
}
- return_err_set_type->data.error_set.infer_fn = nullptr;
+ return_err_set_type->data.error_set.incomplete = false;
if (type_is_global_error_set(inferred_err_set_type)) {
return_err_set_type->data.error_set.err_count = UINT32_MAX;
} else {
@@ -7319,6 +7328,30 @@ bool tld_ptr_eql(const Tld *a, const Tld *b) {
return a == b;
}
+uint32_t node_ptr_hash(const AstNode *ptr) {
+ return hash_ptr((void*)ptr);
+}
+
+bool node_ptr_eql(const AstNode *a, const AstNode *b) {
+ return a == b;
+}
+
+uint32_t fn_ptr_hash(const ZigFn *ptr) {
+ return hash_ptr((void*)ptr);
+}
+
+bool fn_ptr_eql(const ZigFn *a, const ZigFn *b) {
+ return a == b;
+}
+
+uint32_t err_ptr_hash(const ErrorTableEntry *ptr) {
+ return hash_ptr((void*)ptr);
+}
+
+bool err_ptr_eql(const ErrorTableEntry *a, const ErrorTableEntry *b) {
+ return a == b;
+}
+
ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name) {
Tld *tld = get_container_scope(codegen->compile_var_import)->decl_table.get(buf_create_from_str(name));
resolve_top_level_decl(codegen, tld, nullptr, false);
@@ -7331,7 +7364,7 @@ ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name) {
bool type_is_global_error_set(ZigType *err_set_type) {
assert(err_set_type->id == ZigTypeIdErrorSet);
- assert(err_set_type->data.error_set.infer_fn == nullptr);
+ assert(!err_set_type->data.error_set.incomplete);
return err_set_type->data.error_set.err_count == UINT32_MAX;
}
diff --git a/src/ast_render.cpp b/src/ast_render.cpp
index 537a74d7b1..18940c4b80 100644
--- a/src/ast_render.cpp
+++ b/src/ast_render.cpp
@@ -266,6 +266,8 @@ static const char *node_type_str(NodeType node_type) {
return "AnyFrameType";
case NodeTypeEnumLiteral:
return "EnumLiteral";
+ case NodeTypeErrorSetField:
+ return "ErrorSetField";
}
zig_unreachable();
}
@@ -1177,6 +1179,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
case NodeTypeTestDecl:
case NodeTypeStructField:
case NodeTypeUsingNamespace:
+ case NodeTypeErrorSetField:
zig_panic("TODO more ast rendering");
}
}
diff --git a/src/buffer.hpp b/src/buffer.hpp
index 251b5c2f27..6442e4f123 100644
--- a/src/buffer.hpp
+++ b/src/buffer.hpp
@@ -38,6 +38,12 @@ static inline char *buf_ptr(Buf *buf) {
return buf->list.items;
}
+static inline const char *buf_ptr(const Buf *buf) {
+ assert(buf);
+ assert(buf->list.length);
+ return buf->list.items;
+}
+
static inline void buf_resize(Buf *buf, size_t new_len) {
buf->list.resize(new_len + 1);
buf->list.at(buf_len(buf)) = 0;
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 88ff179ca7..3dbd0b8538 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -8727,6 +8727,9 @@ static void init(CodeGen *g) {
// Be aware of https://github.com/ziglang/zig/issues/3275
target_specific_cpu_args = "";
target_specific_features = riscv_default_features;
+ } else if (g->zig_target->arch == ZigLLVM_x86) {
+ target_specific_cpu_args = "pentium4";
+ target_specific_features = "";
} else {
target_specific_cpu_args = "";
target_specific_features = "";
@@ -10355,15 +10358,15 @@ void codegen_build_and_link(CodeGen *g) {
}
}
if (g->enable_doc_generation) {
- Buf *doc_dir_path = buf_sprintf("%s" OS_SEP "doc", buf_ptr(g->output_dir));
+ Buf *doc_dir_path = buf_sprintf("%s" OS_SEP "docs", buf_ptr(g->output_dir));
if ((err = os_make_path(doc_dir_path))) {
fprintf(stderr, "Unable to create directory %s: %s\n", buf_ptr(doc_dir_path), err_str(err));
exit(1);
}
- Buf *index_html_src_path = buf_sprintf("%s" OS_SEP "special" OS_SEP "doc" OS_SEP "index.html",
+ Buf *index_html_src_path = buf_sprintf("%s" OS_SEP "special" OS_SEP "docs" OS_SEP "index.html",
buf_ptr(g->zig_std_dir));
Buf *index_html_dest_path = buf_sprintf("%s" OS_SEP "index.html", buf_ptr(doc_dir_path));
- Buf *main_js_src_path = buf_sprintf("%s" OS_SEP "special" OS_SEP "doc" OS_SEP "main.js",
+ Buf *main_js_src_path = buf_sprintf("%s" OS_SEP "special" OS_SEP "docs" OS_SEP "main.js",
buf_ptr(g->zig_std_dir));
Buf *main_js_dest_path = buf_sprintf("%s" OS_SEP "main.js", buf_ptr(doc_dir_path));
diff --git a/src/dump_analysis.cpp b/src/dump_analysis.cpp
index 220019c184..168d86a21f 100644
--- a/src/dump_analysis.cpp
+++ b/src/dump_analysis.cpp
@@ -351,6 +351,15 @@ struct AnalDumpCtx {
ZigList<Tld *> decl_list;
HashMap<const Tld *, uint32_t, tld_ptr_hash, tld_ptr_eql> decl_map;
+
+ ZigList<ZigFn *> fn_list;
+ HashMap<const ZigFn *, uint32_t, fn_ptr_hash, fn_ptr_eql> fn_map;
+
+ ZigList<AstNode *> node_list;
+ HashMap<const AstNode *, uint32_t, node_ptr_hash, node_ptr_eql> node_map;
+
+ ZigList<ErrorTableEntry *> err_list;
+ HashMap<const ErrorTableEntry *, uint32_t, err_ptr_hash, err_ptr_eql> err_map;
};
static uint32_t anal_dump_get_type_id(AnalDumpCtx *ctx, ZigType *ty);
@@ -416,6 +425,39 @@ static uint32_t anal_dump_get_file_id(AnalDumpCtx *ctx, Buf *file) {
return file_id;
}
+static uint32_t anal_dump_get_node_id(AnalDumpCtx *ctx, AstNode *node) {
+ uint32_t node_id = ctx->node_list.length;
+ auto existing_entry = ctx->node_map.put_unique(node, node_id);
+ if (existing_entry == nullptr) {
+ ctx->node_list.append(node);
+ } else {
+ node_id = existing_entry->value;
+ }
+ return node_id;
+}
+
+static uint32_t anal_dump_get_fn_id(AnalDumpCtx *ctx, ZigFn *fn) {
+ uint32_t fn_id = ctx->fn_list.length;
+ auto existing_entry = ctx->fn_map.put_unique(fn, fn_id);
+ if (existing_entry == nullptr) {
+ ctx->fn_list.append(fn);
+ } else {
+ fn_id = existing_entry->value;
+ }
+ return fn_id;
+}
+
+static uint32_t anal_dump_get_err_id(AnalDumpCtx *ctx, ErrorTableEntry *err) {
+ uint32_t err_id = ctx->err_list.length;
+ auto existing_entry = ctx->err_map.put_unique(err, err_id);
+ if (existing_entry == nullptr) {
+ ctx->err_list.append(err);
+ } else {
+ err_id = existing_entry->value;
+ }
+ return err_id;
+}
+
static uint32_t anal_dump_get_decl_id(AnalDumpCtx *ctx, Tld *tld) {
uint32_t decl_id = ctx->decl_list.length;
auto existing_entry = ctx->decl_map.put_unique(tld, decl_id);
@@ -475,6 +517,21 @@ static void anal_dump_file_ref(AnalDumpCtx *ctx, Buf *file) {
jw_int(&ctx->jw, file_id);
}
+static void anal_dump_node_ref(AnalDumpCtx *ctx, AstNode *node) {
+ uint32_t node_id = anal_dump_get_node_id(ctx, node);
+ jw_int(&ctx->jw, node_id);
+}
+
+static void anal_dump_fn_ref(AnalDumpCtx *ctx, ZigFn *fn) {
+ uint32_t fn_id = anal_dump_get_fn_id(ctx, fn);
+ jw_int(&ctx->jw, fn_id);
+}
+
+static void anal_dump_err_ref(AnalDumpCtx *ctx, ErrorTableEntry *err) {
+ uint32_t err_id = anal_dump_get_err_id(ctx, err);
+ jw_int(&ctx->jw, err_id);
+}
+
static void anal_dump_decl_ref(AnalDumpCtx *ctx, Tld *tld) {
uint32_t decl_id = anal_dump_get_decl_id(ctx, tld);
jw_int(&ctx->jw, decl_id);
@@ -536,11 +593,8 @@ static void anal_dump_decl(AnalDumpCtx *ctx, Tld *tld) {
jw_object_field(jw, "import");
anal_dump_type_ref(ctx, tld->import);
- jw_object_field(jw, "line");
- jw_int(jw, tld->source_node->line);
-
- jw_object_field(jw, "col");
- jw_int(jw, tld->source_node->column);
+ jw_object_field(jw, "src");
+ anal_dump_node_ref(ctx, tld->source_node);
jw_object_field(jw, "name");
jw_string(jw, buf_ptr(tld->name));
@@ -584,8 +638,10 @@ static void anal_dump_decl(AnalDumpCtx *ctx, Tld *tld) {
jw_object_field(jw, "type");
anal_dump_type_ref(ctx, fn->type_entry);
- }
+ jw_object_field(jw, "value");
+ anal_dump_fn_ref(ctx, fn);
+ }
break;
}
default:
@@ -626,6 +682,19 @@ static void anal_dump_value(AnalDumpCtx *ctx, AstNode *source_node, ZigType *ty,
anal_dump_type_ref(ctx, val_ty);
return;
}
+ case ZigTypeIdFn: {
+ if (value->data.x_ptr.special == ConstPtrSpecialFunction) {
+ ZigFn *val_fn = value->data.x_ptr.data.fn.fn_entry;
+ if (val_fn->type_entry->data.fn.is_generic) {
+ anal_dump_node_ref(ctx, val_fn->proto_node);
+ } else {
+ anal_dump_fn_ref(ctx, val_fn);
+ }
+ } else {
+ jw_null(&ctx->jw);
+ }
+ return;
+ }
default:
jw_null(&ctx->jw);
return;
@@ -633,24 +702,75 @@ static void anal_dump_value(AnalDumpCtx *ctx, AstNode *source_node, ZigType *ty,
zig_unreachable();
}
-static void anal_dump_type(AnalDumpCtx *ctx, ZigType *ty) {
+static void anal_dump_pointer_attrs(AnalDumpCtx *ctx, ZigType *ty) {
JsonWriter *jw = &ctx->jw;
- jw_array_elem(jw);
+ if (ty->data.pointer.explicit_alignment != 0) {
+ jw_object_field(jw, "align");
+ jw_int(jw, ty->data.pointer.explicit_alignment);
+ }
+ if (ty->data.pointer.is_const) {
+ jw_object_field(jw, "const");
+ jw_bool(jw, true);
+ }
+ if (ty->data.pointer.is_volatile) {
+ jw_object_field(jw, "volatile");
+ jw_bool(jw, true);
+ }
+ if (ty->data.pointer.allow_zero) {
+ jw_object_field(jw, "allowZero");
+ jw_bool(jw, true);
+ }
+ if (ty->data.pointer.host_int_bytes != 0) {
+ jw_object_field(jw, "hostIntBytes");
+ jw_int(jw, ty->data.pointer.host_int_bytes);
+
+ jw_object_field(jw, "bitOffsetInHost");
+ jw_int(jw, ty->data.pointer.bit_offset_in_host);
+ }
+
+ jw_object_field(jw, "elem");
+ anal_dump_type_ref(ctx, ty->data.pointer.child_type);
+}
+
+static void anal_dump_struct_field(AnalDumpCtx *ctx, const TypeStructField *struct_field) {
+ JsonWriter *jw = &ctx->jw;
+
jw_begin_object(jw);
jw_object_field(jw, "name");
- jw_string(jw, buf_ptr(&ty->name));
+ jw_string(jw, buf_ptr(struct_field->name));
+
+ jw_object_field(jw, "type");
+ anal_dump_type_ref(ctx, struct_field->type_entry);
+
+ jw_object_field(jw, "src");
+ anal_dump_node_ref(ctx, struct_field->decl_node);
+
+ jw_end_object(jw);
+}
+
+static void anal_dump_type(AnalDumpCtx *ctx, ZigType *ty) {
+ JsonWriter *jw = &ctx->jw;
+ jw_array_elem(jw);
+ jw_begin_object(jw);
jw_object_field(jw, "kind");
jw_int(jw, type_id_index(ty));
switch (ty->id) {
+ case ZigTypeIdMetaType:
+ case ZigTypeIdBool:
+ break;
case ZigTypeIdStruct: {
if (ty->data.structure.is_slice) {
- // TODO
+ jw_object_field(jw, "len");
+ jw_int(jw, 2);
+ anal_dump_pointer_attrs(ctx, ty->data.structure.fields[slice_ptr_index].type_entry);
break;
}
+ jw_object_field(jw, "name");
+ jw_string(jw, buf_ptr(&ty->name));
{
jw_object_field(jw, "pubDecls");
jw_begin_array(jw);
@@ -691,6 +811,17 @@ static void anal_dump_type(AnalDumpCtx *ctx, ZigType *ty) {
jw_end_array(jw);
}
+ {
+ jw_object_field(jw, "fields");
+ jw_begin_array(jw);
+
+ for(size_t i = 0; i < ty->data.structure.src_field_count; i += 1) {
+ jw_array_elem(jw);
+ anal_dump_struct_field(ctx, &ty->data.structure.fields[i]);
+ }
+ jw_end_array(jw);
+ }
+
if (ty->data.structure.root_struct != nullptr) {
Buf *path_buf = ty->data.structure.root_struct->path;
@@ -705,13 +836,167 @@ static void anal_dump_type(AnalDumpCtx *ctx, ZigType *ty) {
jw_int(jw, ty->data.floating.bit_count);
break;
}
+ case ZigTypeIdInt: {
+ if (ty->data.integral.is_signed) {
+ jw_object_field(jw, "i");
+ } else {
+ jw_object_field(jw, "u");
+ }
+ jw_int(jw, ty->data.integral.bit_count);
+ break;
+ }
+ case ZigTypeIdFn: {
+ jw_object_field(jw, "name");
+ jw_string(jw, buf_ptr(&ty->name));
+
+ jw_object_field(jw, "generic");
+ jw_bool(jw, ty->data.fn.is_generic);
+
+ if (ty->data.fn.fn_type_id.return_type != nullptr) {
+ jw_object_field(jw, "ret");
+ anal_dump_type_ref(ctx, ty->data.fn.fn_type_id.return_type);
+ }
+
+ if (ty->data.fn.fn_type_id.param_count != 0) {
+ jw_object_field(jw, "args");
+ jw_begin_array(jw);
+ for (size_t i = 0; i < ty->data.fn.fn_type_id.param_count; i += 1) {
+ jw_array_elem(jw);
+ if (ty->data.fn.fn_type_id.param_info[i].type != nullptr) {
+ anal_dump_type_ref(ctx, ty->data.fn.fn_type_id.param_info[i].type);
+ } else {
+ jw_null(jw);
+ }
+ }
+ jw_end_array(jw);
+ }
+ break;
+ }
+ case ZigTypeIdPointer: {
+ switch (ty->data.pointer.ptr_len) {
+ case PtrLenSingle:
+ break;
+ case PtrLenUnknown:
+ jw_object_field(jw, "len");
+ jw_int(jw, 1);
+ break;
+ case PtrLenC:
+ jw_object_field(jw, "len");
+ jw_int(jw, 3);
+ break;
+ }
+ anal_dump_pointer_attrs(ctx, ty);
+ break;
+ }
+ case ZigTypeIdErrorSet: {
+ if (type_is_global_error_set(ty)) {
+ break;
+ }
+ jw_object_field(jw, "name");
+ jw_string(jw, buf_ptr(&ty->name));
+
+ if (ty->data.error_set.infer_fn != nullptr) {
+ jw_object_field(jw, "fn");
+ anal_dump_fn_ref(ctx, ty->data.error_set.infer_fn);
+ }
+ jw_object_field(jw, "errors");
+ jw_begin_array(jw);
+ for (uint32_t i = 0; i < ty->data.error_set.err_count; i += 1) {
+ jw_array_elem(jw);
+ ErrorTableEntry *err = ty->data.error_set.errors[i];
+ anal_dump_err_ref(ctx, err);
+ }
+ jw_end_array(jw);
+ break;
+ }
+ case ZigTypeIdErrorUnion: {
+ jw_object_field(jw, "err");
+ anal_dump_type_ref(ctx, ty->data.error_union.err_set_type);
+
+ jw_object_field(jw, "payload");
+ anal_dump_type_ref(ctx, ty->data.error_union.payload_type);
+
+ break;
+ }
default:
- // TODO
+ jw_object_field(jw, "name");
+ jw_string(jw, buf_ptr(&ty->name));
break;
}
jw_end_object(jw);
}
+static void anal_dump_node(AnalDumpCtx *ctx, const AstNode *node) {
+ JsonWriter *jw = &ctx->jw;
+
+ jw_begin_object(jw);
+
+ jw_object_field(jw, "file");
+ anal_dump_file_ref(ctx, node->owner->data.structure.root_struct->path);
+
+ jw_object_field(jw, "line");
+ jw_int(jw, node->line);
+
+ jw_object_field(jw, "col");
+ jw_int(jw, node->column);
+
+ const Buf *doc_comments_buf;
+ switch (node->type) {
+ case NodeTypeParamDecl:
+ doc_comments_buf = &node->data.param_decl.doc_comments;
+ break;
+ case NodeTypeFnProto:
+ doc_comments_buf = &node->data.fn_proto.doc_comments;
+ break;
+ case NodeTypeVariableDeclaration:
+ doc_comments_buf = &node->data.variable_declaration.doc_comments;
+ break;
+ case NodeTypeErrorSetField:
+ doc_comments_buf = &node->data.err_set_field.doc_comments;
+ break;
+ case NodeTypeStructField:
+ doc_comments_buf = &node->data.struct_field.doc_comments;
+ break;
+ default:
+ doc_comments_buf = nullptr;
+ break;
+ }
+ if (doc_comments_buf != nullptr && doc_comments_buf->list.length != 0) {
+ jw_object_field(jw, "docs");
+ jw_string(jw, buf_ptr(doc_comments_buf));
+ }
+
+ jw_end_object(jw);
+}
+
+static void anal_dump_err(AnalDumpCtx *ctx, const ErrorTableEntry *err) {
+ JsonWriter *jw = &ctx->jw;
+
+ jw_begin_object(jw);
+
+ jw_object_field(jw, "src");
+ anal_dump_node_ref(ctx, err->decl_node);
+
+ jw_object_field(jw, "name");
+ jw_string(jw, buf_ptr(&err->name));
+
+ jw_end_object(jw);
+}
+
+static void anal_dump_fn(AnalDumpCtx *ctx, ZigFn *fn) {
+ JsonWriter *jw = &ctx->jw;
+
+ jw_begin_object(jw);
+
+ jw_object_field(jw, "src");
+ anal_dump_node_ref(ctx, fn->proto_node);
+
+ jw_object_field(jw, "type");
+ anal_dump_type_ref(ctx, fn->type_entry);
+
+ jw_end_object(jw);
+}
+
void zig_print_analysis_dump(CodeGen *g, FILE *f, const char *one_indent, const char *nl) {
Error err;
AnalDumpCtx ctx = {};
@@ -722,6 +1007,9 @@ void zig_print_analysis_dump(CodeGen *g, FILE *f, const char *one_indent, const
ctx.pkg_map.init(16);
ctx.file_map.init(16);
ctx.decl_map.init(16);
+ ctx.node_map.init(16);
+ ctx.fn_map.init(16);
+ ctx.err_map.init(16);
jw_begin_object(jw);
@@ -761,6 +1049,71 @@ void zig_print_analysis_dump(CodeGen *g, FILE *f, const char *one_indent, const
jw_object_field(jw, "rootPkg");
anal_dump_pkg_ref(&ctx, g->root_package);
+ // Poke the functions
+ for (size_t i = 0; i < g->fn_defs.length; i += 1) {
+ ZigFn *fn = g->fn_defs.at(i);
+ (void)anal_dump_get_fn_id(&ctx, fn);
+ }
+
+ jw_object_field(jw, "calls");
+ jw_begin_array(jw);
+ {
+ auto it = g->memoized_fn_eval_table.entry_iterator();
+ for (;;) {
+ auto *entry = it.next();
+ if (!entry)
+ break;
+
+ jw_array_elem(jw);
+ jw_begin_object(jw);
+
+ jw_object_field(jw, "args");
+ jw_begin_object(jw);
+
+ Scope *scope = entry->key;
+ while (scope != nullptr) {
+ if (scope->id == ScopeIdVarDecl) {
+ ZigVar *var = reinterpret_cast<ScopeVarDecl *>(scope)->var;
+ jw_object_field(jw, var->name);
+ jw_begin_object(jw);
+ jw_object_field(jw, "type");
+ anal_dump_type_ref(&ctx, var->var_type);
+ jw_object_field(jw, "value");
+ anal_dump_value(&ctx, scope->source_node, var->var_type, var->const_value);
+ jw_end_object(jw);
+ } else if (scope->id == ScopeIdFnDef) {
+ jw_end_object(jw);
+
+ jw_object_field(jw, "fn");
+ ZigFn *fn = reinterpret_cast<ScopeFnDef *>(scope)->fn_entry;
+ anal_dump_fn_ref(&ctx, fn);
+
+ ConstExprValue *result = entry->value;
+ jw_object_field(jw, "result");
+ jw_begin_object(jw);
+ jw_object_field(jw, "type");
+ anal_dump_type_ref(&ctx, result->type);
+ jw_object_field(jw, "value");
+ anal_dump_value(&ctx, scope->source_node, result->type, result);
+ jw_end_object(jw);
+ break;
+ }
+ scope = scope->parent;
+ }
+ jw_end_object(jw);
+ }
+ }
+ jw_end_array(jw);
+
+ jw_object_field(jw, "fns");
+ jw_begin_array(jw);
+ for (uint32_t i = 0; i < ctx.fn_list.length; i += 1) {
+ ZigFn *fn = ctx.fn_list.at(i);
+ jw_array_elem(jw);
+ anal_dump_fn(&ctx, fn);
+ }
+ jw_end_array(jw);
+
jw_object_field(jw, "packages");
jw_begin_array(jw);
for (uint32_t i = 0; i < ctx.pkg_list.length; i += 1) {
@@ -794,5 +1147,23 @@ void zig_print_analysis_dump(CodeGen *g, FILE *f, const char *one_indent, const
}
jw_end_array(jw);
+ jw_object_field(jw, "errors");
+ jw_begin_array(jw);
+ for (uint32_t i = 0; i < ctx.err_list.length; i += 1) {
+ const ErrorTableEntry *err = ctx.err_list.at(i);
+ jw_array_elem(jw);
+ anal_dump_err(&ctx, err);
+ }
+ jw_end_array(jw);
+
+ jw_object_field(jw, "astNodes");
+ jw_begin_array(jw);
+ for (uint32_t i = 0; i < ctx.node_list.length; i += 1) {
+ const AstNode *node = ctx.node_list.at(i);
+ jw_array_elem(jw);
+ anal_dump_node(&ctx, node);
+ }
+ jw_end_array(jw);
+
jw_end_object(jw);
}
diff --git a/src/ir.cpp b/src/ir.cpp
index 52b59ddcad..f29870e039 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -7892,11 +7892,14 @@ static ZigType *get_error_set_union(CodeGen *g, ErrorTableEntry **errors, ZigTyp
}
uint32_t index = set1->data.error_set.err_count;
+ bool need_comma = false;
for (uint32_t i = 0; i < set2->data.error_set.err_count; i += 1) {
ErrorTableEntry *error_entry = set2->data.error_set.errors[i];
if (errors[error_entry->value] == nullptr) {
errors[error_entry->value] = error_entry;
- buf_appendf(&err_set_type->name, "%s,", buf_ptr(&error_entry->name));
+ const char *comma = need_comma ? "," : "";
+ need_comma = true;
+ buf_appendf(&err_set_type->name, "%s%s", comma, buf_ptr(&error_entry->name));
err_set_type->data.error_set.errors[index] = error_entry;
index += 1;
}
@@ -7927,6 +7930,17 @@ static ZigType *make_err_set_with_one_item(CodeGen *g, Scope *parent_scope, AstN
return err_set_type;
}
+static AstNode *ast_field_to_symbol_node(AstNode *err_set_field_node) {
+ if (err_set_field_node->type == NodeTypeSymbol) {
+ return err_set_field_node;
+ } else if (err_set_field_node->type == NodeTypeErrorSetField) {
+ assert(err_set_field_node->data.err_set_field.field_name->type == NodeTypeSymbol);
+ return err_set_field_node->data.err_set_field.field_name;
+ } else {
+ return err_set_field_node;
+ }
+}
+
static IrInstruction *ir_gen_err_set_decl(IrBuilder *irb, Scope *parent_scope, AstNode *node) {
assert(node->type == NodeTypeErrorSetDecl);
@@ -7945,11 +7959,11 @@ static IrInstruction *ir_gen_err_set_decl(IrBuilder *irb, Scope *parent_scope, A
ErrorTableEntry **errors = allocate<ErrorTableEntry *>(irb->codegen->errors_by_index.length + err_count);
for (uint32_t i = 0; i < err_count; i += 1) {
- AstNode *symbol_node = node->data.err_set_decl.decls.at(i);
- assert(symbol_node->type == NodeTypeSymbol);
+ AstNode *field_node = node->data.err_set_decl.decls.at(i);
+ AstNode *symbol_node = ast_field_to_symbol_node(field_node);
Buf *err_name = symbol_node->data.symbol_expr.symbol;
ErrorTableEntry *err = allocate<ErrorTableEntry>(1);
- err->decl_node = symbol_node;
+ err->decl_node = field_node;
buf_init_from_buf(&err->name, err_name);
auto existing_entry = irb->codegen->error_table.put_unique(err_name, err);
@@ -7965,8 +7979,10 @@ static IrInstruction *ir_gen_err_set_decl(IrBuilder *irb, Scope *parent_scope, A
ErrorTableEntry *prev_err = errors[err->value];
if (prev_err != nullptr) {
- ErrorMsg *msg = add_node_error(irb->codegen, err->decl_node, buf_sprintf("duplicate error: '%s'", buf_ptr(&err->name)));
- add_error_note(irb->codegen, msg, prev_err->decl_node, buf_sprintf("other error here"));
+ ErrorMsg *msg = add_node_error(irb->codegen, ast_field_to_symbol_node(err->decl_node),
+ buf_sprintf("duplicate error: '%s'", buf_ptr(&err->name)));
+ add_error_note(irb->codegen, msg, ast_field_to_symbol_node(prev_err->decl_node),
+ buf_sprintf("other error here"));
return irb->codegen->invalid_instruction;
}
errors[err->value] = err;
@@ -8116,6 +8132,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
case NodeTypeSwitchProng:
case NodeTypeSwitchRange:
case NodeTypeStructField:
+ case NodeTypeErrorSetField:
case NodeTypeFnDef:
case NodeTypeTestDecl:
zig_unreachable();
@@ -9470,6 +9487,14 @@ static void populate_error_set_table(ErrorTableEntry **errors, ZigType *set) {
}
}
+static ErrorTableEntry *better_documented_error(ErrorTableEntry *preferred, ErrorTableEntry *other) {
+ if (preferred->decl_node->type == NodeTypeErrorSetField)
+ return preferred;
+ if (other->decl_node->type == NodeTypeErrorSetField)
+ return other;
+ return preferred;
+}
+
static ZigType *get_error_set_intersection(IrAnalyze *ira, ZigType *set1, ZigType *set2,
AstNode *source_node)
{
@@ -9496,12 +9521,17 @@ static ZigType *get_error_set_intersection(IrAnalyze *ira, ZigType *set1, ZigTyp
buf_resize(&err_set_type->name, 0);
buf_appendf(&err_set_type->name, "error{");
+ bool need_comma = false;
for (uint32_t i = 0; i < set2->data.error_set.err_count; i += 1) {
ErrorTableEntry *error_entry = set2->data.error_set.errors[i];
ErrorTableEntry *existing_entry = errors[error_entry->value];
if (existing_entry != nullptr) {
- intersection_list.append(existing_entry);
- buf_appendf(&err_set_type->name, "%s,", buf_ptr(&existing_entry->name));
+ // prefer the one with docs
+ const char *comma = need_comma ? "," : "";
+ need_comma = true;
+ ErrorTableEntry *existing_entry_with_docs = better_documented_error(existing_entry, error_entry);
+ intersection_list.append(existing_entry_with_docs);
+ buf_appendf(&err_set_type->name, "%s%s", comma, buf_ptr(&existing_entry_with_docs->name));
}
}
free(errors);
@@ -9683,7 +9713,7 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
ZigType *container_set = wanted_type;
// if the container set is inferred, then this will always work.
- if (container_set->data.error_set.infer_fn != nullptr) {
+ if (container_set->data.error_set.infer_fn != nullptr && container_set->data.error_set.incomplete) {
return result;
}
// if the container set is the global one, it will always work.
@@ -12049,7 +12079,7 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa
ZigList<ErrorTableEntry *> *missing_errors = &cast_result->data.error_set_mismatch->missing_errors;
for (size_t i = 0; i < missing_errors->length; i += 1) {
ErrorTableEntry *error_entry = missing_errors->at(i);
- add_error_note(ira->codegen, parent_msg, error_entry->decl_node,
+ add_error_note(ira->codegen, parent_msg, ast_field_to_symbol_node(error_entry->decl_node),
buf_sprintf("'error.%s' not a member of destination error set", buf_ptr(&error_entry->name)));
}
break;
@@ -16148,7 +16178,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
UndefOk);
if (inferred_err_set_type != nullptr) {
- inferred_err_set_type->data.error_set.infer_fn = nullptr;
+ inferred_err_set_type->data.error_set.incomplete = false;
if (result->type->id == ZigTypeIdErrorUnion) {
ErrorTableEntry *err = result->data.x_err_union.error_set->data.x_err_set;
if (err != nullptr) {
@@ -23608,7 +23638,7 @@ static IrInstruction *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstruct
if (!type_is_global_error_set(err_set_type) &&
err_set_type->data.error_set.err_count == 0)
{
- assert(err_set_type->data.error_set.infer_fn == nullptr);
+ assert(!err_set_type->data.error_set.incomplete);
return ir_const_bool(ira, &instruction->base, false);
}
}
diff --git a/src/main.cpp b/src/main.cpp
index 9b8bddabd7..fb2881f3a3 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -34,7 +34,7 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {
" build-exe [source] create executable from source or object files\n"
" build-lib [source] create library from source or object files\n"
" build-obj [source] create object from source or assembly\n"
- " builtin show the source code of that @import(\"builtin\")\n"
+ " builtin show the source code of @import(\"builtin\")\n"
" cc C compiler\n"
" fmt parse files and render in canonical zig format\n"
" id print the base64-encoded compiler id\n"
@@ -65,7 +65,7 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {
" -ftime-report print timing diagnostics\n"
" -fstack-report print stack size diagnostics\n"
" -fdump-analysis write analysis.json file with type information\n"
- " -fgenerate-docs create a doc/ dir with html documentation\n"
+ " -fgenerate-docs create a docs/ dir with html documentation\n"
" --libc [file] Provide a file which specifies libc paths\n"
" --name [name] override output name\n"
" --output-dir [dir] override output directory (defaults to cwd)\n"
diff --git a/src/parser.cpp b/src/parser.cpp
index 96071daa07..9fcf233e2d 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -37,7 +37,7 @@ static AstNode *ast_parse_root(ParseContext *pc);
static AstNodeContainerDecl ast_parse_container_members(ParseContext *pc);
static AstNode *ast_parse_test_decl(ParseContext *pc);
static AstNode *ast_parse_top_level_comptime(ParseContext *pc);
-static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod);
+static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod, Buf *doc_comments);
static AstNode *ast_parse_fn_proto(ParseContext *pc);
static AstNode *ast_parse_var_decl(ParseContext *pc);
static AstNode *ast_parse_container_field(ParseContext *pc);
@@ -497,6 +497,23 @@ static AstNode *ast_parse_root(ParseContext *pc) {
return node;
}
+static Token *ast_parse_doc_comments(ParseContext *pc, Buf *buf) {
+ Token *first_doc_token = nullptr;
+ Token *doc_token = nullptr;
+ while ((doc_token = eat_token_if(pc, TokenIdDocComment))) {
+ if (first_doc_token == nullptr) {
+ first_doc_token = doc_token;
+ }
+ if (buf->list.length == 0) {
+ buf_resize(buf, 0);
+ }
+ // chops off '///' but leaves '\n'
+ buf_append_mem(buf, buf_ptr(pc->buf) + doc_token->start_pos + 3,
+ doc_token->end_pos - doc_token->start_pos - 3);
+ }
+ return first_doc_token;
+}
+
// ContainerMembers
// <- TestDecl ContainerMembers
// / TopLevelComptime ContainerMembers
@@ -519,10 +536,13 @@ static AstNodeContainerDecl ast_parse_container_members(ParseContext *pc) {
continue;
}
+ Buf doc_comment_buf = BUF_INIT;
+ ast_parse_doc_comments(pc, &doc_comment_buf);
+
Token *visib_token = eat_token_if(pc, TokenIdKeywordPub);
VisibMod visib_mod = visib_token != nullptr ? VisibModPub : VisibModPrivate;
- AstNode *top_level_decl = ast_parse_top_level_decl(pc, visib_mod);
+ AstNode *top_level_decl = ast_parse_top_level_decl(pc, visib_mod, &doc_comment_buf);
if (top_level_decl != nullptr) {
res.decls.append(top_level_decl);
continue;
@@ -532,6 +552,7 @@ static AstNodeContainerDecl ast_parse_container_members(ParseContext *pc) {
if (container_field != nullptr) {
assert(container_field->type == NodeTypeStructField);
container_field->data.struct_field.visib_mod = visib_mod;
+ container_field->data.struct_field.doc_comments = doc_comment_buf;
res.fields.append(container_field);
if (eat_token_if(pc, TokenIdComma) != nullptr) {
continue;
@@ -581,7 +602,7 @@ static AstNode *ast_parse_top_level_comptime(ParseContext *pc) {
// <- (KEYWORD_export / KEYWORD_extern STRINGLITERAL? / (KEYWORD_inline / KEYWORD_noinline))? FnProto (SEMICOLON / Block)
// / (KEYWORD_export / KEYWORD_extern STRINGLITERAL?)? KEYWORD_threadlocal? VarDecl
// / KEYWORD_use Expr SEMICOLON
-static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod) {
+static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod, Buf *doc_comments) {
Token *first = eat_token_if(pc, TokenIdKeywordExport);
if (first == nullptr)
first = eat_token_if(pc, TokenIdKeywordExtern);
@@ -603,6 +624,7 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod) {
var_decl->column = first->start_column;
var_decl->data.variable_declaration.threadlocal_tok = thread_local_kw;
var_decl->data.variable_declaration.visib_mod = visib_mod;
+ var_decl->data.variable_declaration.doc_comments = *doc_comments;
var_decl->data.variable_declaration.is_extern = first->id == TokenIdKeywordExtern;
var_decl->data.variable_declaration.is_export = first->id == TokenIdKeywordExport;
var_decl->data.variable_declaration.lib_name = token_buf(lib_name);
@@ -623,6 +645,7 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod) {
fn_proto->line = first->start_line;
fn_proto->column = first->start_column;
fn_proto->data.fn_proto.visib_mod = visib_mod;
+ fn_proto->data.fn_proto.doc_comments = *doc_comments;
fn_proto->data.fn_proto.is_extern = first->id == TokenIdKeywordExtern;
fn_proto->data.fn_proto.is_export = first->id == TokenIdKeywordExport;
switch (first->id) {
@@ -657,6 +680,7 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod) {
if (var_decl != nullptr) {
assert(var_decl->type == NodeTypeVariableDeclaration);
var_decl->data.variable_declaration.visib_mod = visib_mod;
+ var_decl->data.variable_declaration.doc_comments = *doc_comments;
var_decl->data.variable_declaration.threadlocal_tok = thread_local_kw;
return var_decl;
}
@@ -672,6 +696,7 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod) {
assert(fn_proto->type == NodeTypeFnProto);
fn_proto->data.fn_proto.visib_mod = visib_mod;
+ fn_proto->data.fn_proto.doc_comments = *doc_comments;
AstNode *res = fn_proto;
if (body != nullptr) {
res = ast_create_node_copy_line_info(pc, NodeTypeFnDef, fn_proto);
@@ -1719,11 +1744,20 @@ static AstNode *ast_parse_error_set_decl(ParseContext *pc) {
}
ZigList<AstNode *> decls = ast_parse_list<AstNode>(pc, TokenIdComma, [](ParseContext *context) {
+ Buf doc_comment_buf = BUF_INIT;
+ Token *doc_token = ast_parse_doc_comments(context, &doc_comment_buf);
Token *ident = eat_token_if(context, TokenIdSymbol);
if (ident == nullptr)
return (AstNode*)nullptr;
- return token_symbol(context, ident);
+ AstNode *symbol_node = token_symbol(context, ident);
+ if (doc_token == nullptr)
+ return symbol_node;
+
+ AstNode *field_node = ast_create_node(context, NodeTypeErrorSetField, doc_token);
+ field_node->data.err_set_field.field_name = symbol_node;
+ field_node->data.err_set_field.doc_comments = doc_comment_buf;
+ return field_node;
});
expect_token(pc, TokenIdRBrace);
@@ -2057,6 +2091,9 @@ static Optional<AstNodeFnProto> ast_parse_fn_cc(ParseContext *pc) {
// ParamDecl <- (KEYWORD_noalias / KEYWORD_comptime)? (IDENTIFIER COLON)? ParamType
static AstNode *ast_parse_param_decl(ParseContext *pc) {
+ Buf doc_comments = BUF_INIT;
+ ast_parse_doc_comments(pc, &doc_comments);
+
Token *first = eat_token_if(pc, TokenIdKeywordNoAlias);
if (first == nullptr)
first = eat_token_if(pc, TokenIdKeywordCompTime);
@@ -2089,6 +2126,7 @@ static AstNode *ast_parse_param_decl(ParseContext *pc) {
res->line = first->start_line;
res->column = first->start_column;
res->data.param_decl.name = token_buf(name);
+ res->data.param_decl.doc_comments = doc_comments;
res->data.param_decl.is_noalias = first->id == TokenIdKeywordNoAlias;
res->data.param_decl.is_comptime = first->id == TokenIdKeywordCompTime;
return res;
@@ -3029,6 +3067,9 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
case NodeTypeErrorSetDecl:
visit_node_list(&node->data.err_set_decl.decls, visit, context);
break;
+ case NodeTypeErrorSetField:
+ visit_field(&node->data.err_set_field.field_name, visit, context);
+ break;
case NodeTypeResume:
visit_field(&node->data.resume_expr.expr, visit, context);
break;
diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp
index 11824bd871..475c284d27 100644
--- a/src/tokenizer.cpp
+++ b/src/tokenizer.cpp
@@ -197,6 +197,8 @@ enum TokenizeState {
TokenizeStateSawStar,
TokenizeStateSawStarPercent,
TokenizeStateSawSlash,
+ TokenizeStateSawSlash2,
+ TokenizeStateSawSlash3,
TokenizeStateSawBackslash,
TokenizeStateSawPercent,
TokenizeStateSawPlus,
@@ -207,6 +209,7 @@ enum TokenizeState {
TokenizeStateSawCaret,
TokenizeStateSawBar,
TokenizeStateSawBarBar,
+ TokenizeStateDocComment,
TokenizeStateLineComment,
TokenizeStateLineString,
TokenizeStateLineStringEnd,
@@ -912,8 +915,7 @@ void tokenize(Buf *buf, Tokenization *out) {
case TokenizeStateSawSlash:
switch (c) {
case '/':
- cancel_token(&t);
- t.state = TokenizeStateLineComment;
+ t.state = TokenizeStateSawSlash2;
break;
case '=':
set_token_id(&t, t.cur_tok, TokenIdDivEq);
@@ -927,6 +929,38 @@ void tokenize(Buf *buf, Tokenization *out) {
continue;
}
break;
+ case TokenizeStateSawSlash2:
+ switch (c) {
+ case '/':
+ t.state = TokenizeStateSawSlash3;
+ break;
+ case '\n':
+ cancel_token(&t);
+ t.state = TokenizeStateStart;
+ break;
+ default:
+ cancel_token(&t);
+ t.state = TokenizeStateLineComment;
+ break;
+ }
+ break;
+ case TokenizeStateSawSlash3:
+ switch (c) {
+ case '/':
+ cancel_token(&t);
+ t.state = TokenizeStateLineComment;
+ break;
+ case '\n':
+ set_token_id(&t, t.cur_tok, TokenIdDocComment);
+ end_token(&t);
+ t.state = TokenizeStateStart;
+ break;
+ default:
+ set_token_id(&t, t.cur_tok, TokenIdDocComment);
+ t.state = TokenizeStateDocComment;
+ break;
+ }
+ break;
case TokenizeStateSawBackslash:
switch (c) {
case '\\':
@@ -1006,6 +1040,17 @@ void tokenize(Buf *buf, Tokenization *out) {
break;
}
break;
+ case TokenizeStateDocComment:
+ switch (c) {
+ case '\n':
+ end_token(&t);
+ t.state = TokenizeStateStart;
+ break;
+ default:
+ // do nothing
+ break;
+ }
+ break;
case TokenizeStateSymbolFirstC:
switch (c) {
case '"':
@@ -1495,6 +1540,7 @@ void tokenize(Buf *buf, Tokenization *out) {
case TokenizeStateLineStringEnd:
case TokenizeStateSawBarBar:
case TokenizeStateLBracket:
+ case TokenizeStateDocComment:
end_token(&t);
break;
case TokenizeStateSawDotDot:
@@ -1507,6 +1553,8 @@ void tokenize(Buf *buf, Tokenization *out) {
tokenize_error(&t, "unexpected EOF");
break;
case TokenizeStateLineComment:
+ case TokenizeStateSawSlash2:
+ case TokenizeStateSawSlash3:
break;
}
if (t.state != TokenizeStateError) {
@@ -1553,6 +1601,7 @@ const char * token_name(TokenId id) {
case TokenIdComma: return ",";
case TokenIdDash: return "-";
case TokenIdDivEq: return "/=";
+ case TokenIdDocComment: return "DocComment";
case TokenIdDot: return ".";
case TokenIdEllipsis2: return "..";
case TokenIdEllipsis3: return "...";
diff --git a/src/tokenizer.hpp b/src/tokenizer.hpp
index a3d1a60008..e33a82f31d 100644
--- a/src/tokenizer.hpp
+++ b/src/tokenizer.hpp
@@ -42,6 +42,7 @@ enum TokenId {
TokenIdComma,
TokenIdDash,
TokenIdDivEq,
+ TokenIdDocComment,
TokenIdDot,
TokenIdEllipsis2,
TokenIdEllipsis3,