{}.zig
", code.name); + } try out.print("{}", escaped_source);
- const tmp_dir_name = "docgen_tmp";
- try os.makePath(allocator, tmp_dir_name);
const name_plus_ext = try std.fmt.allocPrint(allocator, "{}.zig", code.name);
- const name_plus_bin_ext = try std.fmt.allocPrint(allocator, "{}{}", code.name, exe_ext);
const tmp_source_file_name = try os.path.join(allocator, tmp_dir_name, name_plus_ext);
- const tmp_bin_file_name = try os.path.join(allocator, tmp_dir_name, name_plus_bin_ext);
try io.writeFile(tmp_source_file_name, trimmed_raw_source, null);
switch (code.id) {
- Code.Id.Exe => {
- {
- const args = [][]const u8 {zig_exe, "build-exe", tmp_source_file_name, "--output", tmp_bin_file_name};
- const result = try os.ChildProcess.exec(allocator, args, null, null, max_doc_file_size);
+ Code.Id.Exe => |expected_outcome| {
+ const name_plus_bin_ext = try std.fmt.allocPrint(allocator, "{}{}", code.name, exe_ext);
+ const tmp_bin_file_name = try os.path.join(allocator, tmp_dir_name, name_plus_bin_ext);
+ var build_args = std.ArrayList([]const u8).init(allocator);
+ defer build_args.deinit();
+ try build_args.appendSlice([][]const u8 {zig_exe,
+ "build-exe", tmp_source_file_name,
+ "--output", tmp_bin_file_name,
+ });
+ try out.print("$ zig build-exe {}.zig", code.name);
+ switch (code.mode) {
+ builtin.Mode.Debug => {},
+ builtin.Mode.ReleaseSafe => {
+ try build_args.append("--release-safe");
+ try out.print(" --release-safe");
+ },
+ builtin.Mode.ReleaseFast => {
+ try build_args.append("--release-fast");
+ try out.print(" --release-fast");
+ },
+ }
+ for (code.link_objects) |link_object| {
+ const name_with_ext = try std.fmt.allocPrint(allocator, "{}{}", link_object, obj_ext);
+ const full_path_object = try os.path.join(allocator, tmp_dir_name, name_with_ext);
+ try build_args.append("--object");
+ try build_args.append(full_path_object);
+ try out.print(" --object {}", name_with_ext);
+ }
+ if (code.link_libc) {
+ try build_args.append("--library");
+ try build_args.append("c");
+ try out.print(" --library c");
+ }
+ _ = exec(allocator, build_args.toSliceConst()) catch return parseError(
+ tokenizer, code.source_token, "example failed to compile");
+
+ const run_args = [][]const u8 {tmp_bin_file_name};
+
+ const result = if (expected_outcome == ExpectedOutcome.Fail) blk: {
+ const result = try os.ChildProcess.exec(allocator, run_args, null, null, max_doc_file_size);
switch (result.term) {
os.ChildProcess.Term.Exited => |exit_code| {
- if (exit_code != 0) {
- warn("{}\nThe following command exited with code {}:\n", result.stderr, exit_code);
- for (args) |arg| warn("{} ", arg) else warn("\n");
- return parseError(tokenizer, code.source_token, "example failed to compile");
+ if (exit_code == 0) {
+ warn("{}\nThe following command incorrectly succeeded:\n", result.stderr);
+ for (run_args) |arg| warn("{} ", arg) else warn("\n");
+ return parseError(tokenizer, code.source_token, "example incorrectly compiled");
}
},
- else => {
- warn("{}\nThe following command crashed:\n", result.stderr);
- for (args) |arg| warn("{} ", arg) else warn("\n");
- return parseError(tokenizer, code.source_token, "example failed to compile");
- },
+ else => {},
}
+ break :blk result;
+ } else blk: {
+ break :blk exec(allocator, run_args) catch return parseError(
+ tokenizer, code.source_token, "example crashed");
+ };
+
+
+ const escaped_stderr = try escapeHtml(allocator, result.stderr);
+ const escaped_stdout = try escapeHtml(allocator, result.stdout);
+
+ const colored_stderr = try termColor(allocator, escaped_stderr);
+ const colored_stdout = try termColor(allocator, escaped_stdout);
+
+ try out.print("\n$ ./{}\n{}{}\n", code.name, colored_stdout, colored_stderr);
+ },
+ Code.Id.Test => {
+ var test_args = std.ArrayList([]const u8).init(allocator);
+ defer test_args.deinit();
+
+ try test_args.appendSlice([][]const u8 {zig_exe, "test", tmp_source_file_name});
+ try out.print("$ zig test {}.zig", code.name);
+ switch (code.mode) {
+ builtin.Mode.Debug => {},
+ builtin.Mode.ReleaseSafe => {
+ try test_args.append("--release-safe");
+ try out.print(" --release-safe");
+ },
+ builtin.Mode.ReleaseFast => {
+ try test_args.append("--release-fast");
+ try out.print(" --release-fast");
+ },
}
- const args = [][]const u8 {tmp_bin_file_name};
- const result = try os.ChildProcess.exec(allocator, args, null, null, max_doc_file_size);
+ if (code.target_windows) {
+ try test_args.appendSlice([][]const u8{
+ "--target-os", "windows",
+ "--target-arch", "x86_64",
+ "--target-environ", "msvc",
+ });
+ }
+ const result = exec(allocator, test_args.toSliceConst()) catch return parseError(
+ tokenizer, code.source_token, "test failed");
+ const escaped_stderr = try escapeHtml(allocator, result.stderr);
+ const escaped_stdout = try escapeHtml(allocator, result.stdout);
+ try out.print("\n{}{}\n", escaped_stderr, escaped_stdout);
+ },
+ Code.Id.TestError => |error_match| {
+ var test_args = std.ArrayList([]const u8).init(allocator);
+ defer test_args.deinit();
+
+ try test_args.appendSlice([][]const u8 {zig_exe, "test", "--color", "on", tmp_source_file_name});
+ try out.print("$ zig test {}.zig", code.name);
+ switch (code.mode) {
+ builtin.Mode.Debug => {},
+ builtin.Mode.ReleaseSafe => {
+ try test_args.append("--release-safe");
+ try out.print(" --release-safe");
+ },
+ builtin.Mode.ReleaseFast => {
+ try test_args.append("--release-fast");
+ try out.print(" --release-fast");
+ },
+ }
+ const result = try os.ChildProcess.exec(allocator, test_args.toSliceConst(), null, null, max_doc_file_size);
switch (result.term) {
os.ChildProcess.Term.Exited => |exit_code| {
- if (exit_code != 0) {
- warn("The following command exited with code {}:\n", exit_code);
- for (args) |arg| warn("{} ", arg) else warn("\n");
- return parseError(tokenizer, code.source_token, "example exited with code {}", exit_code);
+ if (exit_code == 0) {
+ warn("{}\nThe following command incorrectly succeeded:\n", result.stderr);
+ for (test_args.toSliceConst()) |arg| warn("{} ", arg) else warn("\n");
+ return parseError(tokenizer, code.source_token, "example incorrectly compiled");
}
},
else => {
- warn("The following command crashed:\n");
- for (args) |arg| warn("{} ", arg) else warn("\n");
- return parseError(tokenizer, code.source_token, "example crashed");
+ warn("{}\nThe following command crashed:\n", result.stderr);
+ for (test_args.toSliceConst()) |arg| warn("{} ", arg) else warn("\n");
+ return parseError(tokenizer, code.source_token, "example compile crashed");
},
}
- try out.print("$ zig build-exe {}.zig\n$ ./{}\n{}{}
\n", code.name, code.name, result.stderr, result.stdout);
+ if (mem.indexOf(u8, result.stderr, error_match) == null) {
+ warn("{}\nExpected to find '{}' in stderr", result.stderr, error_match);
+ return parseError(tokenizer, code.source_token, "example did not have expected compile error");
+ }
+ const escaped_stderr = try escapeHtml(allocator, result.stderr);
+ const colored_stderr = try termColor(allocator, escaped_stderr);
+ try out.print("\n{}\n", colored_stderr);
},
- Code.Id.Test => {
- @panic("TODO");
+
+ Code.Id.TestSafety => |error_match| {
+ var test_args = std.ArrayList([]const u8).init(allocator);
+ defer test_args.deinit();
+
+ try test_args.appendSlice([][]const u8 {zig_exe, "test", tmp_source_file_name});
+ switch (code.mode) {
+ builtin.Mode.Debug => {},
+ builtin.Mode.ReleaseSafe => try test_args.append("--release-safe"),
+ builtin.Mode.ReleaseFast => try test_args.append("--release-fast"),
+ }
+
+ const result = try os.ChildProcess.exec(allocator, test_args.toSliceConst(), null, null, max_doc_file_size);
+ switch (result.term) {
+ os.ChildProcess.Term.Exited => |exit_code| {
+ if (exit_code == 0) {
+ warn("{}\nThe following command incorrectly succeeded:\n", result.stderr);
+ for (test_args.toSliceConst()) |arg| warn("{} ", arg) else warn("\n");
+ return parseError(tokenizer, code.source_token, "example test incorrectly succeeded");
+ }
+ },
+ else => {
+ warn("{}\nThe following command crashed:\n", result.stderr);
+ for (test_args.toSliceConst()) |arg| warn("{} ", arg) else warn("\n");
+ return parseError(tokenizer, code.source_token, "example compile crashed");
+ },
+ }
+ if (mem.indexOf(u8, result.stderr, error_match) == null) {
+ warn("{}\nExpected to find '{}' in stderr", result.stderr, error_match);
+ return parseError(tokenizer, code.source_token, "example did not have expected debug safety error message");
+ }
+ const escaped_stderr = try escapeHtml(allocator, result.stderr);
+ const colored_stderr = try termColor(allocator, escaped_stderr);
+ try out.print("$ zig test {}.zig\n{}\n", code.name, colored_stderr);
},
- Code.Id.Error => {
- @panic("TODO");
+ Code.Id.Obj => {
+ const name_plus_obj_ext = try std.fmt.allocPrint(allocator, "{}{}", code.name, obj_ext);
+ const tmp_obj_file_name = try os.path.join(allocator, tmp_dir_name, name_plus_obj_ext);
+ var build_args = std.ArrayList([]const u8).init(allocator);
+ defer build_args.deinit();
+
+ try build_args.appendSlice([][]const u8 {zig_exe, "build-obj", tmp_source_file_name,
+ "--output", tmp_obj_file_name});
+
+ if (!code.is_inline) {
+ try out.print("$ zig build-obj {}.zig", code.name);
+ }
+
+ switch (code.mode) {
+ builtin.Mode.Debug => {},
+ builtin.Mode.ReleaseSafe => {
+ try build_args.append("--release-safe");
+ if (!code.is_inline) {
+ try out.print(" --release-safe");
+ }
+ },
+ builtin.Mode.ReleaseFast => {
+ try build_args.append("--release-fast");
+ if (!code.is_inline) {
+ try out.print(" --release-fast");
+ }
+ },
+ }
+
+ _ = exec(allocator, build_args.toSliceConst()) catch return parseError(
+ tokenizer, code.source_token, "example failed to compile");
+ if (!code.is_inline) {
+ try out.print("\n");
+ }
},
}
+ warn("OK\n");
},
}
}
}
+
+error ChildCrashed;
+error ChildExitError;
+
+fn exec(allocator: &mem.Allocator, args: []const []const u8) -> %os.ChildProcess.ExecResult {
+ const result = try os.ChildProcess.exec(allocator, args, null, null, max_doc_file_size);
+ switch (result.term) {
+ os.ChildProcess.Term.Exited => |exit_code| {
+ if (exit_code != 0) {
+ warn("{}\nThe following command exited with code {}:\n", result.stderr, exit_code);
+ for (args) |arg| warn("{} ", arg) else warn("\n");
+ return error.ChildExitError;
+ }
+ },
+ else => {
+ warn("{}\nThe following command crashed:\n", result.stderr);
+ for (args) |arg| warn("{} ", arg) else warn("\n");
+ return error.ChildCrashed;
+ },
+ }
+ return result;
+}
diff --git a/doc/langref.html.in b/doc/langref.html.in
index 11952cd17d..884f3b85ae 100644
--- a/doc/langref.html.in
+++ b/doc/langref.html.in
@@ -4,7 +4,9 @@