diff --git a/CMakeLists.txt b/CMakeLists.txt index 9226d56e47..d384bc1b3a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -393,7 +393,7 @@ if(MSVC) ) else() set_target_properties(embedded_softfloat PROPERTIES - COMPILE_FLAGS "-std=c99" + COMPILE_FLAGS "-std=c99 -O3" ) endif() target_include_directories(embedded_softfloat PUBLIC @@ -412,7 +412,9 @@ set(ZIG_SOURCES "${CMAKE_SOURCE_DIR}/src/bigint.cpp" "${CMAKE_SOURCE_DIR}/src/buffer.cpp" "${CMAKE_SOURCE_DIR}/src/c_tokenizer.cpp" + "${CMAKE_SOURCE_DIR}/src/cache_hash.cpp" "${CMAKE_SOURCE_DIR}/src/codegen.cpp" + "${CMAKE_SOURCE_DIR}/src/compiler.cpp" "${CMAKE_SOURCE_DIR}/src/errmsg.cpp" "${CMAKE_SOURCE_DIR}/src/error.cpp" "${CMAKE_SOURCE_DIR}/src/ir.cpp" @@ -427,6 +429,9 @@ set(ZIG_SOURCES "${CMAKE_SOURCE_DIR}/src/util.cpp" "${CMAKE_SOURCE_DIR}/src/translate_c.cpp" ) +set(BLAKE_SOURCES + "${CMAKE_SOURCE_DIR}/src/blake2b.c" +) set(ZIG_CPP_SOURCES "${CMAKE_SOURCE_DIR}/src/zig_llvm.cpp" "${CMAKE_SOURCE_DIR}/src/windows_sdk.cpp" @@ -793,6 +798,7 @@ else() set(EXE_CFLAGS "${EXE_CFLAGS} -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -D_GNU_SOURCE -fno-exceptions -fno-rtti -Werror=strict-prototypes -Werror=old-style-definition -Werror=type-limits -Wno-missing-braces") endif() +set(BLAKE_CFLAGS "-std=c99") set(EXE_LDFLAGS " ") if(MINGW) @@ -814,6 +820,11 @@ set_target_properties(zig_cpp PROPERTIES COMPILE_FLAGS ${EXE_CFLAGS} ) +add_library(embedded_blake STATIC ${BLAKE_SOURCES}) +set_target_properties(embedded_blake PROPERTIES + COMPILE_FLAGS "${BLAKE_CFLAGS} -O3" +) + add_executable(zig ${ZIG_SOURCES}) set_target_properties(zig PROPERTIES COMPILE_FLAGS ${EXE_CFLAGS} @@ -822,6 +833,7 @@ set_target_properties(zig PROPERTIES target_link_libraries(zig LINK_PUBLIC zig_cpp + embedded_blake ${SOFTFLOAT_LIBRARIES} ${CLANG_LIBRARIES} ${LLD_LIBRARIES} diff --git a/build.zig b/build.zig index 6584e5ab1f..0bb4808dc5 100644 --- a/build.zig +++ b/build.zig @@ -16,11 +16,12 @@ pub fn build(b: *Builder) !void { var docgen_exe = b.addExecutable("docgen", "doc/docgen.zig"); const rel_zig_exe = try os.path.relative(b.allocator, b.build_root, b.zig_exe); + const langref_out_path = os.path.join(b.allocator, b.cache_root, "langref.html") catch unreachable; var docgen_cmd = b.addCommand(null, b.env_map, [][]const u8{ docgen_exe.getOutputPath(), rel_zig_exe, "doc" ++ os.path.sep_str ++ "langref.html.in", - os.path.join(b.allocator, b.cache_root, "langref.html") catch unreachable, + langref_out_path, }); docgen_cmd.step.dependOn(&docgen_exe.step); @@ -61,6 +62,9 @@ pub fn build(b: *Builder) !void { b.default_step.dependOn(&exe.step); const skip_release = b.option(bool, "skip-release", "Main test suite skips release builds") orelse false; + const skip_release_small = b.option(bool, "skip-release-small", "Main test suite skips release-small builds") orelse skip_release; + const skip_release_fast = b.option(bool, "skip-release-fast", "Main test suite skips release-fast builds") orelse skip_release; + const skip_release_safe = b.option(bool, "skip-release-safe", "Main test suite skips release-safe builds") orelse skip_release; const skip_self_hosted = b.option(bool, "skip-self-hosted", "Main test suite skips building self hosted compiler") orelse false; if (!skip_self_hosted) { test_step.dependOn(&exe.step); @@ -76,15 +80,29 @@ pub fn build(b: *Builder) !void { const test_stage2_step = b.step("test-stage2", "Run the stage2 compiler tests"); test_stage2_step.dependOn(&test_stage2.step); - test_step.dependOn(test_stage2_step); - const all_modes = []builtin.Mode{ - builtin.Mode.Debug, - builtin.Mode.ReleaseSafe, - builtin.Mode.ReleaseFast, - builtin.Mode.ReleaseSmall, - }; - const modes = if (skip_release) []builtin.Mode{builtin.Mode.Debug} else all_modes; + // TODO see https://github.com/ziglang/zig/issues/1364 + if (false) { + test_step.dependOn(test_stage2_step); + } + + var chosen_modes: [4]builtin.Mode = undefined; + var chosen_mode_index: usize = 0; + chosen_modes[chosen_mode_index] = builtin.Mode.Debug; + chosen_mode_index += 1; + if (!skip_release_safe) { + chosen_modes[chosen_mode_index] = builtin.Mode.ReleaseSafe; + chosen_mode_index += 1; + } + if (!skip_release_fast) { + chosen_modes[chosen_mode_index] = builtin.Mode.ReleaseFast; + chosen_mode_index += 1; + } + if (!skip_release_small) { + chosen_modes[chosen_mode_index] = builtin.Mode.ReleaseSmall; + chosen_mode_index += 1; + } + const modes = chosen_modes[0..chosen_mode_index]; test_step.dependOn(tests.addPkgTests(b, test_filter, "test/behavior.zig", "behavior", "Run the behavior tests", modes)); diff --git a/ci/appveyor/build_script.bat b/ci/appveyor/build_script.bat index 179bd88d7e..ae56418216 100644 --- a/ci/appveyor/build_script.bat +++ b/ci/appveyor/build_script.bat @@ -23,4 +23,4 @@ cd %ZIGBUILDDIR% cmake.exe .. -Thost=x64 -G"Visual Studio 14 2015 Win64" "-DCMAKE_INSTALL_PREFIX=%ZIGBUILDDIR%" "-DCMAKE_PREFIX_PATH=%ZIGPREFIXPATH%" -DCMAKE_BUILD_TYPE=Release || exit /b msbuild /p:Configuration=Release INSTALL.vcxproj || exit /b -bin\zig.exe build --build-file ..\build.zig test || exit /b +bin\zig.exe build --build-file ..\build.zig test -Dskip-release || exit /b diff --git a/ci/travis_linux_script b/ci/travis_linux_script index 1c449bc8a8..428230912b 100755 --- a/ci/travis_linux_script +++ b/ci/travis_linux_script @@ -8,9 +8,9 @@ export CXX=clang++-7.0 echo $PATH mkdir build cd build -cmake .. -DCMAKE_INSTALL_PREFIX=$(pwd) +cmake .. -DCMAKE_BUILD_TYPE=Release make -j2 install -./zig build --build-file ../build.zig test +./zig build --build-file ../build.zig test -Dskip-release-small if [ "${TRAVIS_PULL_REQUEST}" = "false" ]; then mkdir $TRAVIS_BUILD_DIR/artifacts diff --git a/ci/travis_osx_script b/ci/travis_osx_script index 2616f42a7c..69c026f3a2 100755 --- a/ci/travis_osx_script +++ b/ci/travis_osx_script @@ -5,8 +5,8 @@ set -e mkdir build cd build -cmake .. -DCMAKE_PREFIX_PATH=/usr/local/opt/llvm@7/ -DCMAKE_INSTALL_PREFIX=$(pwd) +cmake .. -DCMAKE_PREFIX_PATH=/usr/local/opt/llvm@7/ -DCMAKE_BUILD_TYPE=Release make VERBOSE=1 make install -./zig build --build-file ../build.zig test +./zig build --build-file ../build.zig test -Dskip-release-small diff --git a/doc/docgen.zig b/doc/docgen.zig index c1158dc03f..2ee53bbb99 100644 --- a/doc/docgen.zig +++ b/doc/docgen.zig @@ -11,6 +11,7 @@ const max_doc_file_size = 10 * 1024 * 1024; const exe_ext = std.build.Target(std.build.Target.Native).exeFileExt(); const obj_ext = std.build.Target(std.build.Target.Native).oFileExt(); const tmp_dir_name = "docgen_tmp"; +const test_out_path = tmp_dir_name ++ os.path.sep_str ++ "test" ++ exe_ext; pub fn main() !void { var direct_allocator = std.heap.DirectAllocator.init(); @@ -299,6 +300,7 @@ const Node = union(enum) { SeeAlso: []const SeeAlsoItem, Code: Code, Link: Link, + Syntax: Token, }; const Toc = struct { @@ -529,6 +531,17 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc { }, }); tokenizer.code_node_count += 1; + } else if (mem.eql(u8, tag_name, "syntax")) { + _ = try eatToken(tokenizer, Token.Id.BracketClose); + const content_tok = try eatToken(tokenizer, Token.Id.Content); + _ = try eatToken(tokenizer, Token.Id.BracketOpen); + const end_syntax_tag = try eatToken(tokenizer, Token.Id.TagContent); + const end_tag_name = tokenizer.buffer[end_syntax_tag.start..end_syntax_tag.end]; + if (!mem.eql(u8, end_tag_name, "endsyntax")) { + return parseError(tokenizer, end_syntax_tag, "invalid token inside syntax: {}", end_tag_name); + } + _ = try eatToken(tokenizer, Token.Id.BracketClose); + try nodes.append(Node{ .Syntax = content_tok }); } else { return parseError(tokenizer, tag_token, "unrecognized tag name: {}", tag_name); } @@ -570,6 +583,11 @@ fn escapeHtml(allocator: *mem.Allocator, input: []const u8) ![]u8 { var buf_adapter = io.BufferOutStream.init(&buf); var out = &buf_adapter.stream; + try writeEscaped(out, input); + return buf.toOwnedSlice(); +} + +fn writeEscaped(out: var, input: []const u8) !void { for (input) |c| { try switch (c) { '&' => out.write("&"), @@ -579,7 +597,6 @@ fn escapeHtml(allocator: *mem.Allocator, input: []const u8) ![]u8 { else => out.writeByte(c), }; } - return buf.toOwnedSlice(); } //#define VT_RED "\x1b[31;1m" @@ -686,6 +703,230 @@ fn termColor(allocator: *mem.Allocator, input: []const u8) ![]u8 { return buf.toOwnedSlice(); } +const builtin_types = [][]const u8{ + "f16", "f32", "f64", "f128", "c_longdouble", "c_short", + "c_ushort", "c_int", "c_uint", "c_long", "c_ulong", "c_longlong", + "c_ulonglong", "c_char", "c_void", "void", "bool", "isize", + "usize", "noreturn", "type", "error", "comptime_int", "comptime_float", +}; + +fn isType(name: []const u8) bool { + for (builtin_types) |t| { + if (mem.eql(u8, t, name)) + return true; + } + return false; +} + +fn tokenizeAndPrint(allocator: *mem.Allocator, docgen_tokenizer: *Tokenizer, out: var, source_token: Token) !void { + const raw_src = docgen_tokenizer.buffer[source_token.start..source_token.end]; + const src = mem.trim(u8, raw_src, " \n"); + try out.write(""); + var tokenizer = std.zig.Tokenizer.init(src); + var index: usize = 0; + var next_tok_is_fn = false; + while (true) { + const prev_tok_was_fn = next_tok_is_fn; + next_tok_is_fn = false; + + const token = tokenizer.next(); + try writeEscaped(out, src[index..token.start]); + switch (token.id) { + std.zig.Token.Id.Eof => break, + + std.zig.Token.Id.Keyword_align, + std.zig.Token.Id.Keyword_and, + std.zig.Token.Id.Keyword_asm, + std.zig.Token.Id.Keyword_async, + std.zig.Token.Id.Keyword_await, + std.zig.Token.Id.Keyword_break, + std.zig.Token.Id.Keyword_cancel, + std.zig.Token.Id.Keyword_catch, + std.zig.Token.Id.Keyword_comptime, + std.zig.Token.Id.Keyword_const, + std.zig.Token.Id.Keyword_continue, + std.zig.Token.Id.Keyword_defer, + std.zig.Token.Id.Keyword_else, + std.zig.Token.Id.Keyword_enum, + std.zig.Token.Id.Keyword_errdefer, + std.zig.Token.Id.Keyword_error, + std.zig.Token.Id.Keyword_export, + std.zig.Token.Id.Keyword_extern, + std.zig.Token.Id.Keyword_for, + std.zig.Token.Id.Keyword_if, + std.zig.Token.Id.Keyword_inline, + std.zig.Token.Id.Keyword_nakedcc, + std.zig.Token.Id.Keyword_noalias, + std.zig.Token.Id.Keyword_or, + std.zig.Token.Id.Keyword_orelse, + std.zig.Token.Id.Keyword_packed, + std.zig.Token.Id.Keyword_promise, + std.zig.Token.Id.Keyword_pub, + std.zig.Token.Id.Keyword_resume, + std.zig.Token.Id.Keyword_return, + std.zig.Token.Id.Keyword_section, + std.zig.Token.Id.Keyword_stdcallcc, + std.zig.Token.Id.Keyword_struct, + std.zig.Token.Id.Keyword_suspend, + std.zig.Token.Id.Keyword_switch, + std.zig.Token.Id.Keyword_test, + std.zig.Token.Id.Keyword_try, + std.zig.Token.Id.Keyword_union, + std.zig.Token.Id.Keyword_unreachable, + std.zig.Token.Id.Keyword_use, + std.zig.Token.Id.Keyword_var, + std.zig.Token.Id.Keyword_volatile, + std.zig.Token.Id.Keyword_while, + => { + try out.write(""); + try writeEscaped(out, src[token.start..token.end]); + try out.write(""); + }, + + std.zig.Token.Id.Keyword_fn => { + try out.write(""); + try writeEscaped(out, src[token.start..token.end]); + try out.write(""); + next_tok_is_fn = true; + }, + + std.zig.Token.Id.Keyword_undefined, + std.zig.Token.Id.Keyword_null, + std.zig.Token.Id.Keyword_true, + std.zig.Token.Id.Keyword_false, + std.zig.Token.Id.Keyword_this, + => { + try out.write(""); + try writeEscaped(out, src[token.start..token.end]); + try out.write(""); + }, + + std.zig.Token.Id.StringLiteral, + std.zig.Token.Id.MultilineStringLiteralLine, + std.zig.Token.Id.CharLiteral, + => { + try out.write(""); + try writeEscaped(out, src[token.start..token.end]); + try out.write(""); + }, + + std.zig.Token.Id.Builtin => { + try out.write(""); + try writeEscaped(out, src[token.start..token.end]); + try out.write(""); + }, + + std.zig.Token.Id.LineComment, + std.zig.Token.Id.DocComment, + => { + try out.write(""); + try writeEscaped(out, src[token.start..token.end]); + try out.write(""); + }, + + std.zig.Token.Id.Identifier => { + if (prev_tok_was_fn) { + try out.write(""); + try writeEscaped(out, src[token.start..token.end]); + try out.write(""); + } else { + const is_int = blk: { + if (src[token.start] != 'i' and src[token.start] != 'u') + break :blk false; + var i = token.start + 1; + if (i == token.end) + break :blk false; + while (i != token.end) : (i += 1) { + if (src[i] < '0' or src[i] > '9') + break :blk false; + } + break :blk true; + }; + if (is_int or isType(src[token.start..token.end])) { + try out.write(""); + try writeEscaped(out, src[token.start..token.end]); + try out.write(""); + } else { + try writeEscaped(out, src[token.start..token.end]); + } + } + }, + + std.zig.Token.Id.IntegerLiteral, + std.zig.Token.Id.FloatLiteral, + => { + try out.write(""); + try writeEscaped(out, src[token.start..token.end]); + try out.write(""); + }, + + std.zig.Token.Id.Bang, + std.zig.Token.Id.Pipe, + std.zig.Token.Id.PipePipe, + std.zig.Token.Id.PipeEqual, + std.zig.Token.Id.Equal, + std.zig.Token.Id.EqualEqual, + std.zig.Token.Id.EqualAngleBracketRight, + std.zig.Token.Id.BangEqual, + std.zig.Token.Id.LParen, + std.zig.Token.Id.RParen, + std.zig.Token.Id.Semicolon, + std.zig.Token.Id.Percent, + std.zig.Token.Id.PercentEqual, + std.zig.Token.Id.LBrace, + std.zig.Token.Id.RBrace, + std.zig.Token.Id.LBracket, + std.zig.Token.Id.RBracket, + std.zig.Token.Id.Period, + std.zig.Token.Id.Ellipsis2, + std.zig.Token.Id.Ellipsis3, + std.zig.Token.Id.Caret, + std.zig.Token.Id.CaretEqual, + std.zig.Token.Id.Plus, + std.zig.Token.Id.PlusPlus, + std.zig.Token.Id.PlusEqual, + std.zig.Token.Id.PlusPercent, + std.zig.Token.Id.PlusPercentEqual, + std.zig.Token.Id.Minus, + std.zig.Token.Id.MinusEqual, + std.zig.Token.Id.MinusPercent, + std.zig.Token.Id.MinusPercentEqual, + std.zig.Token.Id.Asterisk, + std.zig.Token.Id.AsteriskEqual, + std.zig.Token.Id.AsteriskAsterisk, + std.zig.Token.Id.AsteriskPercent, + std.zig.Token.Id.AsteriskPercentEqual, + std.zig.Token.Id.Arrow, + std.zig.Token.Id.Colon, + std.zig.Token.Id.Slash, + std.zig.Token.Id.SlashEqual, + std.zig.Token.Id.Comma, + std.zig.Token.Id.Ampersand, + std.zig.Token.Id.AmpersandEqual, + std.zig.Token.Id.QuestionMark, + std.zig.Token.Id.AngleBracketLeft, + std.zig.Token.Id.AngleBracketLeftEqual, + std.zig.Token.Id.AngleBracketAngleBracketLeft, + std.zig.Token.Id.AngleBracketAngleBracketLeftEqual, + std.zig.Token.Id.AngleBracketRight, + std.zig.Token.Id.AngleBracketRightEqual, + std.zig.Token.Id.AngleBracketAngleBracketRight, + std.zig.Token.Id.AngleBracketAngleBracketRightEqual, + std.zig.Token.Id.Tilde, + std.zig.Token.Id.BracketStarBracket, + => try writeEscaped(out, src[token.start..token.end]), + + std.zig.Token.Id.Invalid => return parseError( + docgen_tokenizer, + source_token, + "syntax error", + ), + } + index = token.end; + } + try out.write(""); +} + fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var, zig_exe: []const u8) !void { var code_progress_index: usize = 0; @@ -725,17 +966,21 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var } try out.write("\n"); }, + Node.Syntax => |content_tok| { + try tokenizeAndPrint(allocator, tokenizer, out, content_tok); + }, Node.Code => |code| { code_progress_index += 1; warn("docgen example code {}/{}...", code_progress_index, tokenizer.code_node_count); const raw_source = tokenizer.buffer[code.source_token.start..code.source_token.end]; const trimmed_raw_source = mem.trim(u8, raw_source, " \n"); - const escaped_source = try escapeHtml(allocator, trimmed_raw_source); if (!code.is_inline) { try out.print("

{}.zig

", code.name); } - try out.print("
{}
", escaped_source); + try out.write("
");
+                try tokenizeAndPrint(allocator, tokenizer, out, code.source_token);
+                try out.write("
"); const name_plus_ext = try std.fmt.allocPrint(allocator, "{}.zig", code.name); const tmp_source_file_name = try os.path.join(allocator, tmp_dir_name, name_plus_ext); try io.writeFile(tmp_source_file_name, trimmed_raw_source); @@ -821,6 +1066,8 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var zig_exe, "test", tmp_source_file_name, + "--output", + test_out_path, }); try out.print("
$ zig test {}.zig", code.name);
                         switch (code.mode) {
@@ -863,6 +1110,8 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
                             "--color",
                             "on",
                             tmp_source_file_name,
+                            "--output",
+                            test_out_path,
                         });
                         try out.print("
$ zig test {}.zig", code.name);
                         switch (code.mode) {
@@ -918,6 +1167,8 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
                             zig_exe,
                             "test",
                             tmp_source_file_name,
+                            "--output",
+                            test_out_path,
                         });
                         switch (code.mode) {
                             builtin.Mode.Debug => {},
diff --git a/doc/langref.html.in b/doc/langref.html.in
index 8fa80996af..f5b92873e0 100644
--- a/doc/langref.html.in
+++ b/doc/langref.html.in
@@ -5,9 +5,6 @@
     
     Documentation - The Zig Programming Language
     
-