syntax: functions require return type. remove ->
The purpose of this is: * Only one way to do things * Changing a function with void return type to return a possible error becomes a 1 character change, subtly encouraging people to use errors. See #632 Here are some imperfect sed commands for performing this update: remove arrow: ``` sed -i 's/\(\bfn\b.*\)-> /\1/g' $(find . -name "*.zig") ``` add void: ``` sed -i 's/\(\bfn\b.*\))\s*{/\1) void {/g' $(find ../ -name "*.zig") ``` Some cleanup may be necessary, but this should do the bulk of the work.
This commit is contained in:
parent
e5bc5873d7
commit
3671582c15
14
build.zig
14
build.zig
@ -10,7 +10,7 @@ const ArrayList = std.ArrayList;
|
|||||||
const Buffer = std.Buffer;
|
const Buffer = std.Buffer;
|
||||||
const io = std.io;
|
const io = std.io;
|
||||||
|
|
||||||
pub fn build(b: &Builder) -> %void {
|
pub fn build(b: &Builder) %void {
|
||||||
const mode = b.standardReleaseOptions();
|
const mode = b.standardReleaseOptions();
|
||||||
|
|
||||||
var docgen_exe = b.addExecutable("docgen", "doc/docgen.zig");
|
var docgen_exe = b.addExecutable("docgen", "doc/docgen.zig");
|
||||||
@ -121,7 +121,7 @@ pub fn build(b: &Builder) -> %void {
|
|||||||
test_step.dependOn(tests.addGenHTests(b, test_filter));
|
test_step.dependOn(tests.addGenHTests(b, test_filter));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dependOnLib(lib_exe_obj: &std.build.LibExeObjStep, dep: &const LibraryDep) {
|
fn dependOnLib(lib_exe_obj: &std.build.LibExeObjStep, dep: &const LibraryDep) void {
|
||||||
for (dep.libdirs.toSliceConst()) |lib_dir| {
|
for (dep.libdirs.toSliceConst()) |lib_dir| {
|
||||||
lib_exe_obj.addLibPath(lib_dir);
|
lib_exe_obj.addLibPath(lib_dir);
|
||||||
}
|
}
|
||||||
@ -136,7 +136,7 @@ fn dependOnLib(lib_exe_obj: &std.build.LibExeObjStep, dep: &const LibraryDep) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn addCppLib(b: &Builder, lib_exe_obj: &std.build.LibExeObjStep, cmake_binary_dir: []const u8, lib_name: []const u8) {
|
fn addCppLib(b: &Builder, lib_exe_obj: &std.build.LibExeObjStep, cmake_binary_dir: []const u8, lib_name: []const u8) void {
|
||||||
const lib_prefix = if (lib_exe_obj.target.isWindows()) "" else "lib";
|
const lib_prefix = if (lib_exe_obj.target.isWindows()) "" else "lib";
|
||||||
lib_exe_obj.addObjectFile(os.path.join(b.allocator, cmake_binary_dir, "zig_cpp",
|
lib_exe_obj.addObjectFile(os.path.join(b.allocator, cmake_binary_dir, "zig_cpp",
|
||||||
b.fmt("{}{}{}", lib_prefix, lib_name, lib_exe_obj.target.libFileExt())) catch unreachable);
|
b.fmt("{}{}{}", lib_prefix, lib_name, lib_exe_obj.target.libFileExt())) catch unreachable);
|
||||||
@ -149,7 +149,7 @@ const LibraryDep = struct {
|
|||||||
includes: ArrayList([]const u8),
|
includes: ArrayList([]const u8),
|
||||||
};
|
};
|
||||||
|
|
||||||
fn findLLVM(b: &Builder, llvm_config_exe: []const u8) -> %LibraryDep {
|
fn findLLVM(b: &Builder, llvm_config_exe: []const u8) %LibraryDep {
|
||||||
const libs_output = try b.exec([][]const u8{llvm_config_exe, "--libs", "--system-libs"});
|
const libs_output = try b.exec([][]const u8{llvm_config_exe, "--libs", "--system-libs"});
|
||||||
const includes_output = try b.exec([][]const u8{llvm_config_exe, "--includedir"});
|
const includes_output = try b.exec([][]const u8{llvm_config_exe, "--includedir"});
|
||||||
const libdir_output = try b.exec([][]const u8{llvm_config_exe, "--libdir"});
|
const libdir_output = try b.exec([][]const u8{llvm_config_exe, "--libdir"});
|
||||||
@ -197,7 +197,7 @@ fn findLLVM(b: &Builder, llvm_config_exe: []const u8) -> %LibraryDep {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn installStdLib(b: &Builder, stdlib_files: []const u8) {
|
pub fn installStdLib(b: &Builder, stdlib_files: []const u8) void {
|
||||||
var it = mem.split(stdlib_files, ";");
|
var it = mem.split(stdlib_files, ";");
|
||||||
while (it.next()) |stdlib_file| {
|
while (it.next()) |stdlib_file| {
|
||||||
const src_path = os.path.join(b.allocator, "std", stdlib_file) catch unreachable;
|
const src_path = os.path.join(b.allocator, "std", stdlib_file) catch unreachable;
|
||||||
@ -206,7 +206,7 @@ pub fn installStdLib(b: &Builder, stdlib_files: []const u8) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn installCHeaders(b: &Builder, c_header_files: []const u8) {
|
pub fn installCHeaders(b: &Builder, c_header_files: []const u8) void {
|
||||||
var it = mem.split(c_header_files, ";");
|
var it = mem.split(c_header_files, ";");
|
||||||
while (it.next()) |c_header_file| {
|
while (it.next()) |c_header_file| {
|
||||||
const src_path = os.path.join(b.allocator, "c_headers", c_header_file) catch unreachable;
|
const src_path = os.path.join(b.allocator, "c_headers", c_header_file) catch unreachable;
|
||||||
@ -215,7 +215,7 @@ pub fn installCHeaders(b: &Builder, c_header_files: []const u8) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn nextValue(index: &usize, build_info: []const u8) -> []const u8 {
|
fn nextValue(index: &usize, build_info: []const u8) []const u8 {
|
||||||
const start = *index;
|
const start = *index;
|
||||||
while (true) : (*index += 1) {
|
while (true) : (*index += 1) {
|
||||||
switch (build_info[*index]) {
|
switch (build_info[*index]) {
|
||||||
|
@ -12,7 +12,7 @@ const exe_ext = std.build.Target(std.build.Target.Native).exeFileExt();
|
|||||||
const obj_ext = std.build.Target(std.build.Target.Native).oFileExt();
|
const obj_ext = std.build.Target(std.build.Target.Native).oFileExt();
|
||||||
const tmp_dir_name = "docgen_tmp";
|
const tmp_dir_name = "docgen_tmp";
|
||||||
|
|
||||||
pub fn main() -> %void {
|
pub fn main() %void {
|
||||||
// TODO use a more general purpose allocator here
|
// TODO use a more general purpose allocator here
|
||||||
var inc_allocator = try std.heap.IncrementingAllocator.init(max_doc_file_size);
|
var inc_allocator = try std.heap.IncrementingAllocator.init(max_doc_file_size);
|
||||||
defer inc_allocator.deinit();
|
defer inc_allocator.deinit();
|
||||||
@ -91,7 +91,7 @@ const Tokenizer = struct {
|
|||||||
Eof,
|
Eof,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn init(source_file_name: []const u8, buffer: []const u8) -> Tokenizer {
|
fn init(source_file_name: []const u8, buffer: []const u8) Tokenizer {
|
||||||
return Tokenizer {
|
return Tokenizer {
|
||||||
.buffer = buffer,
|
.buffer = buffer,
|
||||||
.index = 0,
|
.index = 0,
|
||||||
@ -101,7 +101,7 @@ const Tokenizer = struct {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next(self: &Tokenizer) -> Token {
|
fn next(self: &Tokenizer) Token {
|
||||||
var result = Token {
|
var result = Token {
|
||||||
.id = Token.Id.Eof,
|
.id = Token.Id.Eof,
|
||||||
.start = self.index,
|
.start = self.index,
|
||||||
@ -193,7 +193,7 @@ const Tokenizer = struct {
|
|||||||
line_end: usize,
|
line_end: usize,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn getTokenLocation(self: &Tokenizer, token: &const Token) -> Location {
|
fn getTokenLocation(self: &Tokenizer, token: &const Token) Location {
|
||||||
var loc = Location {
|
var loc = Location {
|
||||||
.line = 0,
|
.line = 0,
|
||||||
.column = 0,
|
.column = 0,
|
||||||
@ -220,7 +220,7 @@ const Tokenizer = struct {
|
|||||||
|
|
||||||
error ParseError;
|
error ParseError;
|
||||||
|
|
||||||
fn parseError(tokenizer: &Tokenizer, token: &const Token, comptime fmt: []const u8, args: ...) -> error {
|
fn parseError(tokenizer: &Tokenizer, token: &const Token, comptime fmt: []const u8, args: ...) error {
|
||||||
const loc = tokenizer.getTokenLocation(token);
|
const loc = tokenizer.getTokenLocation(token);
|
||||||
warn("{}:{}:{}: error: " ++ fmt ++ "\n", tokenizer.source_file_name, loc.line + 1, loc.column + 1, args);
|
warn("{}:{}:{}: error: " ++ fmt ++ "\n", tokenizer.source_file_name, loc.line + 1, loc.column + 1, args);
|
||||||
if (loc.line_start <= loc.line_end) {
|
if (loc.line_start <= loc.line_end) {
|
||||||
@ -243,13 +243,13 @@ fn parseError(tokenizer: &Tokenizer, token: &const Token, comptime fmt: []const
|
|||||||
return error.ParseError;
|
return error.ParseError;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn assertToken(tokenizer: &Tokenizer, token: &const Token, id: Token.Id) -> %void {
|
fn assertToken(tokenizer: &Tokenizer, token: &const Token, id: Token.Id) %void {
|
||||||
if (token.id != id) {
|
if (token.id != id) {
|
||||||
return parseError(tokenizer, token, "expected {}, found {}", @tagName(id), @tagName(token.id));
|
return parseError(tokenizer, token, "expected {}, found {}", @tagName(id), @tagName(token.id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eatToken(tokenizer: &Tokenizer, id: Token.Id) -> %Token {
|
fn eatToken(tokenizer: &Tokenizer, id: Token.Id) %Token {
|
||||||
const token = tokenizer.next();
|
const token = tokenizer.next();
|
||||||
try assertToken(tokenizer, token, id);
|
try assertToken(tokenizer, token, id);
|
||||||
return token;
|
return token;
|
||||||
@ -316,7 +316,7 @@ const Action = enum {
|
|||||||
Close,
|
Close,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn genToc(allocator: &mem.Allocator, tokenizer: &Tokenizer) -> %Toc {
|
fn genToc(allocator: &mem.Allocator, tokenizer: &Tokenizer) %Toc {
|
||||||
var urls = std.HashMap([]const u8, Token, mem.hash_slice_u8, mem.eql_slice_u8).init(allocator);
|
var urls = std.HashMap([]const u8, Token, mem.hash_slice_u8, mem.eql_slice_u8).init(allocator);
|
||||||
errdefer urls.deinit();
|
errdefer urls.deinit();
|
||||||
|
|
||||||
@ -540,7 +540,7 @@ fn genToc(allocator: &mem.Allocator, tokenizer: &Tokenizer) -> %Toc {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn urlize(allocator: &mem.Allocator, input: []const u8) -> %[]u8 {
|
fn urlize(allocator: &mem.Allocator, input: []const u8) %[]u8 {
|
||||||
var buf = try std.Buffer.initSize(allocator, 0);
|
var buf = try std.Buffer.initSize(allocator, 0);
|
||||||
defer buf.deinit();
|
defer buf.deinit();
|
||||||
|
|
||||||
@ -560,7 +560,7 @@ fn urlize(allocator: &mem.Allocator, input: []const u8) -> %[]u8 {
|
|||||||
return buf.toOwnedSlice();
|
return buf.toOwnedSlice();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn escapeHtml(allocator: &mem.Allocator, input: []const u8) -> %[]u8 {
|
fn escapeHtml(allocator: &mem.Allocator, input: []const u8) %[]u8 {
|
||||||
var buf = try std.Buffer.initSize(allocator, 0);
|
var buf = try std.Buffer.initSize(allocator, 0);
|
||||||
defer buf.deinit();
|
defer buf.deinit();
|
||||||
|
|
||||||
@ -604,7 +604,7 @@ test "term color" {
|
|||||||
assert(mem.eql(u8, result, "A<span class=\"t32\">green</span>B"));
|
assert(mem.eql(u8, result, "A<span class=\"t32\">green</span>B"));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn termColor(allocator: &mem.Allocator, input: []const u8) -> %[]u8 {
|
fn termColor(allocator: &mem.Allocator, input: []const u8) %[]u8 {
|
||||||
var buf = try std.Buffer.initSize(allocator, 0);
|
var buf = try std.Buffer.initSize(allocator, 0);
|
||||||
defer buf.deinit();
|
defer buf.deinit();
|
||||||
|
|
||||||
@ -686,7 +686,7 @@ fn termColor(allocator: &mem.Allocator, input: []const u8) -> %[]u8 {
|
|||||||
|
|
||||||
error ExampleFailedToCompile;
|
error ExampleFailedToCompile;
|
||||||
|
|
||||||
fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: &io.OutStream, zig_exe: []const u8) -> %void {
|
fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: &io.OutStream, zig_exe: []const u8) %void {
|
||||||
var code_progress_index: usize = 0;
|
var code_progress_index: usize = 0;
|
||||||
for (toc.nodes) |node| {
|
for (toc.nodes) |node| {
|
||||||
switch (node) {
|
switch (node) {
|
||||||
@ -977,7 +977,7 @@ fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: &io
|
|||||||
error ChildCrashed;
|
error ChildCrashed;
|
||||||
error ChildExitError;
|
error ChildExitError;
|
||||||
|
|
||||||
fn exec(allocator: &mem.Allocator, args: []const []const u8) -> %os.ChildProcess.ExecResult {
|
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);
|
const result = try os.ChildProcess.exec(allocator, args, null, null, max_doc_file_size);
|
||||||
switch (result.term) {
|
switch (result.term) {
|
||||||
os.ChildProcess.Term.Exited => |exit_code| {
|
os.ChildProcess.Term.Exited => |exit_code| {
|
||||||
|
@ -86,7 +86,7 @@
|
|||||||
{#code_begin|exe|hello#}
|
{#code_begin|exe|hello#}
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
pub fn main() -> %void {
|
pub fn main() %void {
|
||||||
// If this program is run without stdout attached, exit with an error.
|
// If this program is run without stdout attached, exit with an error.
|
||||||
var stdout_file = try std.io.getStdOut();
|
var stdout_file = try std.io.getStdOut();
|
||||||
// If this program encounters pipe failure when printing to stdout, exit
|
// If this program encounters pipe failure when printing to stdout, exit
|
||||||
@ -102,7 +102,7 @@ pub fn main() -> %void {
|
|||||||
{#code_begin|exe|hello#}
|
{#code_begin|exe|hello#}
|
||||||
const warn = @import("std").debug.warn;
|
const warn = @import("std").debug.warn;
|
||||||
|
|
||||||
pub fn main() -> void {
|
pub fn main() void {
|
||||||
warn("Hello, world!\n");
|
warn("Hello, world!\n");
|
||||||
}
|
}
|
||||||
{#code_end#}
|
{#code_end#}
|
||||||
@ -132,7 +132,7 @@ const assert = std.debug.assert;
|
|||||||
// error declaration, makes `error.ArgNotFound` available
|
// error declaration, makes `error.ArgNotFound` available
|
||||||
error ArgNotFound;
|
error ArgNotFound;
|
||||||
|
|
||||||
pub fn main() -> %void {
|
pub fn main() %void {
|
||||||
// integers
|
// integers
|
||||||
const one_plus_one: i32 = 1 + 1;
|
const one_plus_one: i32 = 1 + 1;
|
||||||
warn("1 + 1 = {}\n", one_plus_one);
|
warn("1 + 1 = {}\n", one_plus_one);
|
||||||
@ -543,7 +543,7 @@ const c_string_literal =
|
|||||||
{#code_begin|test_err|cannot assign to constant#}
|
{#code_begin|test_err|cannot assign to constant#}
|
||||||
const x = 1234;
|
const x = 1234;
|
||||||
|
|
||||||
fn foo() {
|
fn foo() void {
|
||||||
// It works at global scope as well as inside functions.
|
// It works at global scope as well as inside functions.
|
||||||
const y = 5678;
|
const y = 5678;
|
||||||
|
|
||||||
@ -607,7 +607,7 @@ const binary_int = 0b11110000;
|
|||||||
known size, and is vulnerable to undefined behavior.
|
known size, and is vulnerable to undefined behavior.
|
||||||
</p>
|
</p>
|
||||||
{#code_begin|syntax#}
|
{#code_begin|syntax#}
|
||||||
fn divide(a: i32, b: i32) -> i32 {
|
fn divide(a: i32, b: i32) i32 {
|
||||||
return a / b;
|
return a / b;
|
||||||
}
|
}
|
||||||
{#code_end#}
|
{#code_end#}
|
||||||
@ -644,12 +644,12 @@ const yet_another_hex_float = 0x103.70P-5;
|
|||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
const big = f64(1 << 40);
|
const big = f64(1 << 40);
|
||||||
|
|
||||||
export fn foo_strict(x: f64) -> f64 {
|
export fn foo_strict(x: f64) f64 {
|
||||||
@setFloatMode(this, builtin.FloatMode.Strict);
|
@setFloatMode(this, builtin.FloatMode.Strict);
|
||||||
return x + big - big;
|
return x + big - big;
|
||||||
}
|
}
|
||||||
|
|
||||||
export fn foo_optimized(x: f64) -> f64 {
|
export fn foo_optimized(x: f64) f64 {
|
||||||
return x + big - big;
|
return x + big - big;
|
||||||
}
|
}
|
||||||
{#code_end#}
|
{#code_end#}
|
||||||
@ -660,10 +660,10 @@ export fn foo_optimized(x: f64) -> f64 {
|
|||||||
{#code_link_object|foo#}
|
{#code_link_object|foo#}
|
||||||
const warn = @import("std").debug.warn;
|
const warn = @import("std").debug.warn;
|
||||||
|
|
||||||
extern fn foo_strict(x: f64) -> f64;
|
extern fn foo_strict(x: f64) f64;
|
||||||
extern fn foo_optimized(x: f64) -> f64;
|
extern fn foo_optimized(x: f64) f64;
|
||||||
|
|
||||||
pub fn main() -> %void {
|
pub fn main() %void {
|
||||||
const x = 0.001;
|
const x = 0.001;
|
||||||
warn("optimized = {}\n", foo_optimized(x));
|
warn("optimized = {}\n", foo_optimized(x));
|
||||||
warn("strict = {}\n", foo_strict(x));
|
warn("strict = {}\n", foo_strict(x));
|
||||||
@ -1358,7 +1358,7 @@ test "compile-time array initalization" {
|
|||||||
|
|
||||||
// call a function to initialize an array
|
// call a function to initialize an array
|
||||||
var more_points = []Point{makePoint(3)} ** 10;
|
var more_points = []Point{makePoint(3)} ** 10;
|
||||||
fn makePoint(x: i32) -> Point {
|
fn makePoint(x: i32) Point {
|
||||||
return Point {
|
return Point {
|
||||||
.x = x,
|
.x = x,
|
||||||
.y = x * 2,
|
.y = x * 2,
|
||||||
@ -1552,14 +1552,14 @@ test "global variable alignment" {
|
|||||||
assert(@typeOf(slice) == []align(4) u8);
|
assert(@typeOf(slice) == []align(4) u8);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn derp() align(@sizeOf(usize) * 2) -> i32 { return 1234; }
|
fn derp() align(@sizeOf(usize) * 2) i32 { return 1234; }
|
||||||
fn noop1() align(1) {}
|
fn noop1() align(1) void {}
|
||||||
fn noop4() align(4) {}
|
fn noop4() align(4) void {}
|
||||||
|
|
||||||
test "function alignment" {
|
test "function alignment" {
|
||||||
assert(derp() == 1234);
|
assert(derp() == 1234);
|
||||||
assert(@typeOf(noop1) == fn() align(1));
|
assert(@typeOf(noop1) == fn() align(1) void);
|
||||||
assert(@typeOf(noop4) == fn() align(4));
|
assert(@typeOf(noop4) == fn() align(4) void);
|
||||||
noop1();
|
noop1();
|
||||||
noop4();
|
noop4();
|
||||||
}
|
}
|
||||||
@ -1578,7 +1578,7 @@ test "pointer alignment safety" {
|
|||||||
const bytes = ([]u8)(array[0..]);
|
const bytes = ([]u8)(array[0..]);
|
||||||
assert(foo(bytes) == 0x11111111);
|
assert(foo(bytes) == 0x11111111);
|
||||||
}
|
}
|
||||||
fn foo(bytes: []u8) -> u32 {
|
fn foo(bytes: []u8) u32 {
|
||||||
const slice4 = bytes[1..5];
|
const slice4 = bytes[1..5];
|
||||||
const int_slice = ([]u32)(@alignCast(4, slice4));
|
const int_slice = ([]u32)(@alignCast(4, slice4));
|
||||||
return int_slice[0];
|
return int_slice[0];
|
||||||
@ -1710,7 +1710,7 @@ const Vec3 = struct {
|
|||||||
y: f32,
|
y: f32,
|
||||||
z: f32,
|
z: f32,
|
||||||
|
|
||||||
pub fn init(x: f32, y: f32, z: f32) -> Vec3 {
|
pub fn init(x: f32, y: f32, z: f32) Vec3 {
|
||||||
return Vec3 {
|
return Vec3 {
|
||||||
.x = x,
|
.x = x,
|
||||||
.y = y,
|
.y = y,
|
||||||
@ -1718,7 +1718,7 @@ const Vec3 = struct {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dot(self: &const Vec3, other: &const Vec3) -> f32 {
|
pub fn dot(self: &const Vec3, other: &const Vec3) f32 {
|
||||||
return self.x * other.x + self.y * other.y + self.z * other.z;
|
return self.x * other.x + self.y * other.y + self.z * other.z;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -1750,7 +1750,7 @@ test "struct namespaced variable" {
|
|||||||
|
|
||||||
// struct field order is determined by the compiler for optimal performance.
|
// struct field order is determined by the compiler for optimal performance.
|
||||||
// however, you can still calculate a struct base pointer given a field pointer:
|
// however, you can still calculate a struct base pointer given a field pointer:
|
||||||
fn setYBasedOnX(x: &f32, y: f32) {
|
fn setYBasedOnX(x: &f32, y: f32) void {
|
||||||
const point = @fieldParentPtr(Point, "x", x);
|
const point = @fieldParentPtr(Point, "x", x);
|
||||||
point.y = y;
|
point.y = y;
|
||||||
}
|
}
|
||||||
@ -1765,7 +1765,7 @@ test "field parent pointer" {
|
|||||||
|
|
||||||
// You can return a struct from a function. This is how we do generics
|
// You can return a struct from a function. This is how we do generics
|
||||||
// in Zig:
|
// in Zig:
|
||||||
fn LinkedList(comptime T: type) -> type {
|
fn LinkedList(comptime T: type) type {
|
||||||
return struct {
|
return struct {
|
||||||
pub const Node = struct {
|
pub const Node = struct {
|
||||||
prev: ?&Node,
|
prev: ?&Node,
|
||||||
@ -1862,7 +1862,7 @@ const Suit = enum {
|
|||||||
Diamonds,
|
Diamonds,
|
||||||
Hearts,
|
Hearts,
|
||||||
|
|
||||||
pub fn isClubs(self: Suit) -> bool {
|
pub fn isClubs(self: Suit) bool {
|
||||||
return self == Suit.Clubs;
|
return self == Suit.Clubs;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -1919,14 +1919,14 @@ test "@tagName" {
|
|||||||
</p>
|
</p>
|
||||||
{#code_begin|obj_err|parameter of type 'Foo' not allowed in function with calling convention 'ccc'#}
|
{#code_begin|obj_err|parameter of type 'Foo' not allowed in function with calling convention 'ccc'#}
|
||||||
const Foo = enum { A, B, C };
|
const Foo = enum { A, B, C };
|
||||||
export fn entry(foo: Foo) { }
|
export fn entry(foo: Foo) void { }
|
||||||
{#code_end#}
|
{#code_end#}
|
||||||
<p>
|
<p>
|
||||||
For a C-ABI-compatible enum, use <code class="zig">extern enum</code>:
|
For a C-ABI-compatible enum, use <code class="zig">extern enum</code>:
|
||||||
</p>
|
</p>
|
||||||
{#code_begin|obj#}
|
{#code_begin|obj#}
|
||||||
const Foo = extern enum { A, B, C };
|
const Foo = extern enum { A, B, C };
|
||||||
export fn entry(foo: Foo) { }
|
export fn entry(foo: Foo) void { }
|
||||||
{#code_end#}
|
{#code_end#}
|
||||||
{#header_close#}
|
{#header_close#}
|
||||||
<p>TODO packed enum</p>
|
<p>TODO packed enum</p>
|
||||||
@ -2191,7 +2191,7 @@ test "while else" {
|
|||||||
assert(!rangeHasNumber(0, 10, 15));
|
assert(!rangeHasNumber(0, 10, 15));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rangeHasNumber(begin: usize, end: usize, number: usize) -> bool {
|
fn rangeHasNumber(begin: usize, end: usize, number: usize) bool {
|
||||||
var i = begin;
|
var i = begin;
|
||||||
// While loops are expressions. The result of the expression is the
|
// While loops are expressions. The result of the expression is the
|
||||||
// result of the else clause of a while loop, which is executed when
|
// result of the else clause of a while loop, which is executed when
|
||||||
@ -2242,14 +2242,14 @@ test "while null capture" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var numbers_left: u32 = undefined;
|
var numbers_left: u32 = undefined;
|
||||||
fn eventuallyNullSequence() -> ?u32 {
|
fn eventuallyNullSequence() ?u32 {
|
||||||
return if (numbers_left == 0) null else blk: {
|
return if (numbers_left == 0) null else blk: {
|
||||||
numbers_left -= 1;
|
numbers_left -= 1;
|
||||||
break :blk numbers_left;
|
break :blk numbers_left;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
error ReachedZero;
|
error ReachedZero;
|
||||||
fn eventuallyErrorSequence() -> %u32 {
|
fn eventuallyErrorSequence() %u32 {
|
||||||
return if (numbers_left == 0) error.ReachedZero else blk: {
|
return if (numbers_left == 0) error.ReachedZero else blk: {
|
||||||
numbers_left -= 1;
|
numbers_left -= 1;
|
||||||
break :blk numbers_left;
|
break :blk numbers_left;
|
||||||
@ -2274,7 +2274,7 @@ test "inline while loop" {
|
|||||||
assert(sum == 9);
|
assert(sum == 9);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn typeNameLength(comptime T: type) -> usize {
|
fn typeNameLength(comptime T: type) usize {
|
||||||
return @typeName(T).len;
|
return @typeName(T).len;
|
||||||
}
|
}
|
||||||
{#code_end#}
|
{#code_end#}
|
||||||
@ -2367,7 +2367,7 @@ test "inline for loop" {
|
|||||||
assert(sum == 9);
|
assert(sum == 9);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn typeNameLength(comptime T: type) -> usize {
|
fn typeNameLength(comptime T: type) usize {
|
||||||
return @typeName(T).len;
|
return @typeName(T).len;
|
||||||
}
|
}
|
||||||
{#code_end#}
|
{#code_end#}
|
||||||
@ -2493,7 +2493,7 @@ const assert = std.debug.assert;
|
|||||||
const warn = std.debug.warn;
|
const warn = std.debug.warn;
|
||||||
|
|
||||||
// defer will execute an expression at the end of the current scope.
|
// defer will execute an expression at the end of the current scope.
|
||||||
fn deferExample() -> usize {
|
fn deferExample() usize {
|
||||||
var a: usize = 1;
|
var a: usize = 1;
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -2512,7 +2512,7 @@ test "defer basics" {
|
|||||||
|
|
||||||
// If multiple defer statements are specified, they will be executed in
|
// If multiple defer statements are specified, they will be executed in
|
||||||
// the reverse order they were run.
|
// the reverse order they were run.
|
||||||
fn deferUnwindExample() {
|
fn deferUnwindExample() void {
|
||||||
warn("\n");
|
warn("\n");
|
||||||
|
|
||||||
defer {
|
defer {
|
||||||
@ -2539,7 +2539,7 @@ test "defer unwinding" {
|
|||||||
// This is especially useful in allowing a function to clean up properly
|
// This is especially useful in allowing a function to clean up properly
|
||||||
// on error, and replaces goto error handling tactics as seen in c.
|
// on error, and replaces goto error handling tactics as seen in c.
|
||||||
error DeferError;
|
error DeferError;
|
||||||
fn deferErrorExample(is_error: bool) -> %void {
|
fn deferErrorExample(is_error: bool) %void {
|
||||||
warn("\nstart of function\n");
|
warn("\nstart of function\n");
|
||||||
|
|
||||||
// This will always be executed on exit
|
// This will always be executed on exit
|
||||||
@ -2587,7 +2587,7 @@ test "basic math" {
|
|||||||
{#code_end#}
|
{#code_end#}
|
||||||
<p>In fact, this is how assert is implemented:</p>
|
<p>In fact, this is how assert is implemented:</p>
|
||||||
{#code_begin|test_err#}
|
{#code_begin|test_err#}
|
||||||
fn assert(ok: bool) {
|
fn assert(ok: bool) void {
|
||||||
if (!ok) unreachable; // assertion failure
|
if (!ok) unreachable; // assertion failure
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2630,7 +2630,7 @@ test "type of unreachable" {
|
|||||||
the <code>noreturn</code> type is compatible with every other type. Consider:
|
the <code>noreturn</code> type is compatible with every other type. Consider:
|
||||||
</p>
|
</p>
|
||||||
{#code_begin|test#}
|
{#code_begin|test#}
|
||||||
fn foo(condition: bool, b: u32) {
|
fn foo(condition: bool, b: u32) void {
|
||||||
const a = if (condition) b else return;
|
const a = if (condition) b else return;
|
||||||
@panic("do something with a");
|
@panic("do something with a");
|
||||||
}
|
}
|
||||||
@ -2641,14 +2641,14 @@ test "noreturn" {
|
|||||||
<p>Another use case for <code>noreturn</code> is the <code>exit</code> function:</p>
|
<p>Another use case for <code>noreturn</code> is the <code>exit</code> function:</p>
|
||||||
{#code_begin|test#}
|
{#code_begin|test#}
|
||||||
{#target_windows#}
|
{#target_windows#}
|
||||||
pub extern "kernel32" stdcallcc fn ExitProcess(exit_code: c_uint) -> noreturn;
|
pub extern "kernel32" stdcallcc fn ExitProcess(exit_code: c_uint) noreturn;
|
||||||
|
|
||||||
test "foo" {
|
test "foo" {
|
||||||
const value = bar() catch ExitProcess(1);
|
const value = bar() catch ExitProcess(1);
|
||||||
assert(value == 1234);
|
assert(value == 1234);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bar() -> %u32 {
|
fn bar() %u32 {
|
||||||
return 1234;
|
return 1234;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2660,7 +2660,7 @@ const assert = @import("std").debug.assert;
|
|||||||
const assert = @import("std").debug.assert;
|
const assert = @import("std").debug.assert;
|
||||||
|
|
||||||
// Functions are declared like this
|
// Functions are declared like this
|
||||||
fn add(a: i8, b: i8) -> i8 {
|
fn add(a: i8, b: i8) i8 {
|
||||||
if (a == 0) {
|
if (a == 0) {
|
||||||
// You can still return manually if needed.
|
// You can still return manually if needed.
|
||||||
return b;
|
return b;
|
||||||
@ -2671,34 +2671,34 @@ fn add(a: i8, b: i8) -> i8 {
|
|||||||
|
|
||||||
// The export specifier makes a function externally visible in the generated
|
// The export specifier makes a function externally visible in the generated
|
||||||
// object file, and makes it use the C ABI.
|
// object file, and makes it use the C ABI.
|
||||||
export fn sub(a: i8, b: i8) -> i8 { return a - b; }
|
export fn sub(a: i8, b: i8) i8 { return a - b; }
|
||||||
|
|
||||||
// The extern specifier is used to declare a function that will be resolved
|
// The extern specifier is used to declare a function that will be resolved
|
||||||
// at link time, when linking statically, or at runtime, when linking
|
// at link time, when linking statically, or at runtime, when linking
|
||||||
// dynamically.
|
// dynamically.
|
||||||
// The stdcallcc specifier changes the calling convention of the function.
|
// The stdcallcc specifier changes the calling convention of the function.
|
||||||
extern "kernel32" stdcallcc fn ExitProcess(exit_code: u32) -> noreturn;
|
extern "kernel32" stdcallcc fn ExitProcess(exit_code: u32) noreturn;
|
||||||
extern "c" fn atan2(a: f64, b: f64) -> f64;
|
extern "c" fn atan2(a: f64, b: f64) f64;
|
||||||
|
|
||||||
// The @setCold builtin tells the optimizer that a function is rarely called.
|
// The @setCold builtin tells the optimizer that a function is rarely called.
|
||||||
fn abort() -> noreturn {
|
fn abort() noreturn {
|
||||||
@setCold(true);
|
@setCold(true);
|
||||||
while (true) {}
|
while (true) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// nakedcc makes a function not have any function prologue or epilogue.
|
// nakedcc makes a function not have any function prologue or epilogue.
|
||||||
// This can be useful when integrating with assembly.
|
// This can be useful when integrating with assembly.
|
||||||
nakedcc fn _start() -> noreturn {
|
nakedcc fn _start() noreturn {
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
// The pub specifier allows the function to be visible when importing.
|
// The pub specifier allows the function to be visible when importing.
|
||||||
// Another file can use @import and call sub2
|
// Another file can use @import and call sub2
|
||||||
pub fn sub2(a: i8, b: i8) -> i8 { return a - b; }
|
pub fn sub2(a: i8, b: i8) i8 { return a - b; }
|
||||||
|
|
||||||
// Functions can be used as values and are equivalent to pointers.
|
// Functions can be used as values and are equivalent to pointers.
|
||||||
const call2_op = fn (a: i8, b: i8) -> i8;
|
const call2_op = fn (a: i8, b: i8) i8;
|
||||||
fn do_op(fn_call: call2_op, op1: i8, op2: i8) -> i8 {
|
fn do_op(fn_call: call2_op, op1: i8, op2: i8) i8 {
|
||||||
return fn_call(op1, op2);
|
return fn_call(op1, op2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2712,11 +2712,11 @@ test "function" {
|
|||||||
const assert = @import("std").debug.assert;
|
const assert = @import("std").debug.assert;
|
||||||
|
|
||||||
comptime {
|
comptime {
|
||||||
assert(@typeOf(foo) == fn());
|
assert(@typeOf(foo) == fn()void);
|
||||||
assert(@sizeOf(fn()) == @sizeOf(?fn()));
|
assert(@sizeOf(fn()void) == @sizeOf(?fn()void));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn foo() { }
|
fn foo() void { }
|
||||||
{#code_end#}
|
{#code_end#}
|
||||||
{#header_open|Pass-by-value Parameters#}
|
{#header_open|Pass-by-value Parameters#}
|
||||||
<p>
|
<p>
|
||||||
@ -2728,7 +2728,7 @@ const Foo = struct {
|
|||||||
x: i32,
|
x: i32,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn bar(foo: Foo) {}
|
fn bar(foo: Foo) void {}
|
||||||
|
|
||||||
test "pass aggregate type by value to function" {
|
test "pass aggregate type by value to function" {
|
||||||
bar(Foo {.x = 12,});
|
bar(Foo {.x = 12,});
|
||||||
@ -2743,7 +2743,7 @@ const Foo = struct {
|
|||||||
x: i32,
|
x: i32,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn bar(foo: &const Foo) {}
|
fn bar(foo: &const Foo) void {}
|
||||||
|
|
||||||
test "implicitly cast to const pointer" {
|
test "implicitly cast to const pointer" {
|
||||||
bar(Foo {.x = 12,});
|
bar(Foo {.x = 12,});
|
||||||
@ -2798,7 +2798,7 @@ error UnexpectedToken;
|
|||||||
error InvalidChar;
|
error InvalidChar;
|
||||||
error Overflow;
|
error Overflow;
|
||||||
|
|
||||||
pub fn parseU64(buf: []const u8, radix: u8) -> %u64 {
|
pub fn parseU64(buf: []const u8, radix: u8) %u64 {
|
||||||
var x: u64 = 0;
|
var x: u64 = 0;
|
||||||
|
|
||||||
for (buf) |c| {
|
for (buf) |c| {
|
||||||
@ -2822,7 +2822,7 @@ pub fn parseU64(buf: []const u8, radix: u8) -> %u64 {
|
|||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn charToDigit(c: u8) -> u8 {
|
fn charToDigit(c: u8) u8 {
|
||||||
return switch (c) {
|
return switch (c) {
|
||||||
'0' ... '9' => c - '0',
|
'0' ... '9' => c - '0',
|
||||||
'A' ... 'Z' => c - 'A' + 10,
|
'A' ... 'Z' => c - 'A' + 10,
|
||||||
@ -2857,7 +2857,7 @@ test "parse u64" {
|
|||||||
</ul>
|
</ul>
|
||||||
<p>If you want to provide a default value, you can use the <code>catch</code> binary operator:</p>
|
<p>If you want to provide a default value, you can use the <code>catch</code> binary operator:</p>
|
||||||
{#code_begin|syntax#}
|
{#code_begin|syntax#}
|
||||||
fn doAThing(str: []u8) {
|
fn doAThing(str: []u8) void {
|
||||||
const number = parseU64(str, 10) catch 13;
|
const number = parseU64(str, 10) catch 13;
|
||||||
// ...
|
// ...
|
||||||
}
|
}
|
||||||
@ -2870,7 +2870,7 @@ fn doAThing(str: []u8) {
|
|||||||
<p>Let's say you wanted to return the error if you got one, otherwise continue with the
|
<p>Let's say you wanted to return the error if you got one, otherwise continue with the
|
||||||
function logic:</p>
|
function logic:</p>
|
||||||
{#code_begin|syntax#}
|
{#code_begin|syntax#}
|
||||||
fn doAThing(str: []u8) -> %void {
|
fn doAThing(str: []u8) %void {
|
||||||
const number = parseU64(str, 10) catch |err| return err;
|
const number = parseU64(str, 10) catch |err| return err;
|
||||||
// ...
|
// ...
|
||||||
}
|
}
|
||||||
@ -2879,7 +2879,7 @@ fn doAThing(str: []u8) -> %void {
|
|||||||
There is a shortcut for this. The <code>try</code> expression:
|
There is a shortcut for this. The <code>try</code> expression:
|
||||||
</p>
|
</p>
|
||||||
{#code_begin|syntax#}
|
{#code_begin|syntax#}
|
||||||
fn doAThing(str: []u8) -> %void {
|
fn doAThing(str: []u8) %void {
|
||||||
const number = try parseU64(str, 10);
|
const number = try parseU64(str, 10);
|
||||||
// ...
|
// ...
|
||||||
}
|
}
|
||||||
@ -2907,7 +2907,7 @@ fn doAThing(str: []u8) -> %void {
|
|||||||
the <code>if</code> and <code>switch</code> expression:
|
the <code>if</code> and <code>switch</code> expression:
|
||||||
</p>
|
</p>
|
||||||
{#code_begin|syntax#}
|
{#code_begin|syntax#}
|
||||||
fn doAThing(str: []u8) {
|
fn doAThing(str: []u8) void {
|
||||||
if (parseU64(str, 10)) |number| {
|
if (parseU64(str, 10)) |number| {
|
||||||
doSomethingWithNumber(number);
|
doSomethingWithNumber(number);
|
||||||
} else |err| switch (err) {
|
} else |err| switch (err) {
|
||||||
@ -2929,7 +2929,7 @@ fn doAThing(str: []u8) {
|
|||||||
Example:
|
Example:
|
||||||
</p>
|
</p>
|
||||||
{#code_begin|syntax#}
|
{#code_begin|syntax#}
|
||||||
fn createFoo(param: i32) -> %Foo {
|
fn createFoo(param: i32) %Foo {
|
||||||
const foo = try tryToAllocateFoo();
|
const foo = try tryToAllocateFoo();
|
||||||
// now we have allocated foo. we need to free it if the function fails.
|
// now we have allocated foo. we need to free it if the function fails.
|
||||||
// but we want to return it if the function succeeds.
|
// but we want to return it if the function succeeds.
|
||||||
@ -3018,9 +3018,9 @@ struct Foo *do_a_thing(void) {
|
|||||||
<p>Zig code</p>
|
<p>Zig code</p>
|
||||||
{#code_begin|syntax#}
|
{#code_begin|syntax#}
|
||||||
// malloc prototype included for reference
|
// malloc prototype included for reference
|
||||||
extern fn malloc(size: size_t) -> ?&u8;
|
extern fn malloc(size: size_t) ?&u8;
|
||||||
|
|
||||||
fn doAThing() -> ?&Foo {
|
fn doAThing() ?&Foo {
|
||||||
const ptr = malloc(1234) ?? return null;
|
const ptr = malloc(1234) ?? return null;
|
||||||
// ...
|
// ...
|
||||||
}
|
}
|
||||||
@ -3047,7 +3047,7 @@ fn doAThing() -> ?&Foo {
|
|||||||
In Zig you can accomplish the same thing:
|
In Zig you can accomplish the same thing:
|
||||||
</p>
|
</p>
|
||||||
{#code_begin|syntax#}
|
{#code_begin|syntax#}
|
||||||
fn doAThing(nullable_foo: ?&Foo) {
|
fn doAThing(nullable_foo: ?&Foo) void {
|
||||||
// do some stuff
|
// do some stuff
|
||||||
|
|
||||||
if (nullable_foo) |foo| {
|
if (nullable_foo) |foo| {
|
||||||
@ -3104,13 +3104,13 @@ fn doAThing(nullable_foo: ?&Foo) {
|
|||||||
Compile-time parameters is how Zig implements generics. It is compile-time duck typing.
|
Compile-time parameters is how Zig implements generics. It is compile-time duck typing.
|
||||||
</p>
|
</p>
|
||||||
{#code_begin|syntax#}
|
{#code_begin|syntax#}
|
||||||
fn max(comptime T: type, a: T, b: T) -> T {
|
fn max(comptime T: type, a: T, b: T) T {
|
||||||
return if (a > b) a else b;
|
return if (a > b) a else b;
|
||||||
}
|
}
|
||||||
fn gimmeTheBiggerFloat(a: f32, b: f32) -> f32 {
|
fn gimmeTheBiggerFloat(a: f32, b: f32) f32 {
|
||||||
return max(f32, a, b);
|
return max(f32, a, b);
|
||||||
}
|
}
|
||||||
fn gimmeTheBiggerInteger(a: u64, b: u64) -> u64 {
|
fn gimmeTheBiggerInteger(a: u64, b: u64) u64 {
|
||||||
return max(u64, a, b);
|
return max(u64, a, b);
|
||||||
}
|
}
|
||||||
{#code_end#}
|
{#code_end#}
|
||||||
@ -3132,13 +3132,13 @@ fn gimmeTheBiggerInteger(a: u64, b: u64) -> u64 {
|
|||||||
For example, if we were to introduce another function to the above snippet:
|
For example, if we were to introduce another function to the above snippet:
|
||||||
</p>
|
</p>
|
||||||
{#code_begin|test_err|unable to evaluate constant expression#}
|
{#code_begin|test_err|unable to evaluate constant expression#}
|
||||||
fn max(comptime T: type, a: T, b: T) -> T {
|
fn max(comptime T: type, a: T, b: T) T {
|
||||||
return if (a > b) a else b;
|
return if (a > b) a else b;
|
||||||
}
|
}
|
||||||
test "try to pass a runtime type" {
|
test "try to pass a runtime type" {
|
||||||
foo(false);
|
foo(false);
|
||||||
}
|
}
|
||||||
fn foo(condition: bool) {
|
fn foo(condition: bool) void {
|
||||||
const result = max(
|
const result = max(
|
||||||
if (condition) f32 else u64,
|
if (condition) f32 else u64,
|
||||||
1234,
|
1234,
|
||||||
@ -3157,7 +3157,7 @@ fn foo(condition: bool) {
|
|||||||
For example:
|
For example:
|
||||||
</p>
|
</p>
|
||||||
{#code_begin|test_err|operator not allowed for type 'bool'#}
|
{#code_begin|test_err|operator not allowed for type 'bool'#}
|
||||||
fn max(comptime T: type, a: T, b: T) -> T {
|
fn max(comptime T: type, a: T, b: T) T {
|
||||||
return if (a > b) a else b;
|
return if (a > b) a else b;
|
||||||
}
|
}
|
||||||
test "try to compare bools" {
|
test "try to compare bools" {
|
||||||
@ -3170,7 +3170,7 @@ test "try to compare bools" {
|
|||||||
if we wanted to:
|
if we wanted to:
|
||||||
</p>
|
</p>
|
||||||
{#code_begin|test#}
|
{#code_begin|test#}
|
||||||
fn max(comptime T: type, a: T, b: T) -> T {
|
fn max(comptime T: type, a: T, b: T) T {
|
||||||
if (T == bool) {
|
if (T == bool) {
|
||||||
return a or b;
|
return a or b;
|
||||||
} else if (a > b) {
|
} else if (a > b) {
|
||||||
@ -3193,7 +3193,7 @@ test "try to compare bools" {
|
|||||||
this:
|
this:
|
||||||
</p>
|
</p>
|
||||||
{#code_begin|syntax#}
|
{#code_begin|syntax#}
|
||||||
fn max(a: bool, b: bool) -> bool {
|
fn max(a: bool, b: bool) bool {
|
||||||
return a or b;
|
return a or b;
|
||||||
}
|
}
|
||||||
{#code_end#}
|
{#code_end#}
|
||||||
@ -3224,7 +3224,7 @@ const assert = @import("std").debug.assert;
|
|||||||
|
|
||||||
const CmdFn = struct {
|
const CmdFn = struct {
|
||||||
name: []const u8,
|
name: []const u8,
|
||||||
func: fn(i32) -> i32,
|
func: fn(i32) i32,
|
||||||
};
|
};
|
||||||
|
|
||||||
const cmd_fns = []CmdFn{
|
const cmd_fns = []CmdFn{
|
||||||
@ -3232,11 +3232,11 @@ const cmd_fns = []CmdFn{
|
|||||||
CmdFn {.name = "two", .func = two},
|
CmdFn {.name = "two", .func = two},
|
||||||
CmdFn {.name = "three", .func = three},
|
CmdFn {.name = "three", .func = three},
|
||||||
};
|
};
|
||||||
fn one(value: i32) -> i32 { return value + 1; }
|
fn one(value: i32) i32 { return value + 1; }
|
||||||
fn two(value: i32) -> i32 { return value + 2; }
|
fn two(value: i32) i32 { return value + 2; }
|
||||||
fn three(value: i32) -> i32 { return value + 3; }
|
fn three(value: i32) i32 { return value + 3; }
|
||||||
|
|
||||||
fn performFn(comptime prefix_char: u8, start_value: i32) -> i32 {
|
fn performFn(comptime prefix_char: u8, start_value: i32) i32 {
|
||||||
var result: i32 = start_value;
|
var result: i32 = start_value;
|
||||||
comptime var i = 0;
|
comptime var i = 0;
|
||||||
inline while (i < cmd_fns.len) : (i += 1) {
|
inline while (i < cmd_fns.len) : (i += 1) {
|
||||||
@ -3262,7 +3262,7 @@ test "perform fn" {
|
|||||||
{#code_begin|syntax#}
|
{#code_begin|syntax#}
|
||||||
// From the line:
|
// From the line:
|
||||||
// assert(performFn('t', 1) == 6);
|
// assert(performFn('t', 1) == 6);
|
||||||
fn performFn(start_value: i32) -> i32 {
|
fn performFn(start_value: i32) i32 {
|
||||||
var result: i32 = start_value;
|
var result: i32 = start_value;
|
||||||
result = two(result);
|
result = two(result);
|
||||||
result = three(result);
|
result = three(result);
|
||||||
@ -3272,7 +3272,7 @@ fn performFn(start_value: i32) -> i32 {
|
|||||||
{#code_begin|syntax#}
|
{#code_begin|syntax#}
|
||||||
// From the line:
|
// From the line:
|
||||||
// assert(performFn('o', 0) == 1);
|
// assert(performFn('o', 0) == 1);
|
||||||
fn performFn(start_value: i32) -> i32 {
|
fn performFn(start_value: i32) i32 {
|
||||||
var result: i32 = start_value;
|
var result: i32 = start_value;
|
||||||
result = one(result);
|
result = one(result);
|
||||||
return result;
|
return result;
|
||||||
@ -3281,7 +3281,7 @@ fn performFn(start_value: i32) -> i32 {
|
|||||||
{#code_begin|syntax#}
|
{#code_begin|syntax#}
|
||||||
// From the line:
|
// From the line:
|
||||||
// assert(performFn('w', 99) == 99);
|
// assert(performFn('w', 99) == 99);
|
||||||
fn performFn(start_value: i32) -> i32 {
|
fn performFn(start_value: i32) i32 {
|
||||||
var result: i32 = start_value;
|
var result: i32 = start_value;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -3302,7 +3302,7 @@ fn performFn(start_value: i32) -> i32 {
|
|||||||
If this cannot be accomplished, the compiler will emit an error. For example:
|
If this cannot be accomplished, the compiler will emit an error. For example:
|
||||||
</p>
|
</p>
|
||||||
{#code_begin|test_err|unable to evaluate constant expression#}
|
{#code_begin|test_err|unable to evaluate constant expression#}
|
||||||
extern fn exit() -> noreturn;
|
extern fn exit() noreturn;
|
||||||
|
|
||||||
test "foo" {
|
test "foo" {
|
||||||
comptime {
|
comptime {
|
||||||
@ -3335,7 +3335,7 @@ test "foo" {
|
|||||||
{#code_begin|test#}
|
{#code_begin|test#}
|
||||||
const assert = @import("std").debug.assert;
|
const assert = @import("std").debug.assert;
|
||||||
|
|
||||||
fn fibonacci(index: u32) -> u32 {
|
fn fibonacci(index: u32) u32 {
|
||||||
if (index < 2) return index;
|
if (index < 2) return index;
|
||||||
return fibonacci(index - 1) + fibonacci(index - 2);
|
return fibonacci(index - 1) + fibonacci(index - 2);
|
||||||
}
|
}
|
||||||
@ -3356,7 +3356,7 @@ test "fibonacci" {
|
|||||||
{#code_begin|test_err|operation caused overflow#}
|
{#code_begin|test_err|operation caused overflow#}
|
||||||
const assert = @import("std").debug.assert;
|
const assert = @import("std").debug.assert;
|
||||||
|
|
||||||
fn fibonacci(index: u32) -> u32 {
|
fn fibonacci(index: u32) u32 {
|
||||||
//if (index < 2) return index;
|
//if (index < 2) return index;
|
||||||
return fibonacci(index - 1) + fibonacci(index - 2);
|
return fibonacci(index - 1) + fibonacci(index - 2);
|
||||||
}
|
}
|
||||||
@ -3379,7 +3379,7 @@ test "fibonacci" {
|
|||||||
{#code_begin|test_err|evaluation exceeded 1000 backwards branches#}
|
{#code_begin|test_err|evaluation exceeded 1000 backwards branches#}
|
||||||
const assert = @import("std").debug.assert;
|
const assert = @import("std").debug.assert;
|
||||||
|
|
||||||
fn fibonacci(index: i32) -> i32 {
|
fn fibonacci(index: i32) i32 {
|
||||||
//if (index < 2) return index;
|
//if (index < 2) return index;
|
||||||
return fibonacci(index - 1) + fibonacci(index - 2);
|
return fibonacci(index - 1) + fibonacci(index - 2);
|
||||||
}
|
}
|
||||||
@ -3402,7 +3402,7 @@ test "fibonacci" {
|
|||||||
{#code_begin|test_err|encountered @panic at compile-time#}
|
{#code_begin|test_err|encountered @panic at compile-time#}
|
||||||
const assert = @import("std").debug.assert;
|
const assert = @import("std").debug.assert;
|
||||||
|
|
||||||
fn fibonacci(index: i32) -> i32 {
|
fn fibonacci(index: i32) i32 {
|
||||||
if (index < 2) return index;
|
if (index < 2) return index;
|
||||||
return fibonacci(index - 1) + fibonacci(index - 2);
|
return fibonacci(index - 1) + fibonacci(index - 2);
|
||||||
}
|
}
|
||||||
@ -3430,7 +3430,7 @@ test "fibonacci" {
|
|||||||
const first_25_primes = firstNPrimes(25);
|
const first_25_primes = firstNPrimes(25);
|
||||||
const sum_of_first_25_primes = sum(first_25_primes);
|
const sum_of_first_25_primes = sum(first_25_primes);
|
||||||
|
|
||||||
fn firstNPrimes(comptime n: usize) -> [n]i32 {
|
fn firstNPrimes(comptime n: usize) [n]i32 {
|
||||||
var prime_list: [n]i32 = undefined;
|
var prime_list: [n]i32 = undefined;
|
||||||
var next_index: usize = 0;
|
var next_index: usize = 0;
|
||||||
var test_number: i32 = 2;
|
var test_number: i32 = 2;
|
||||||
@ -3451,7 +3451,7 @@ fn firstNPrimes(comptime n: usize) -> [n]i32 {
|
|||||||
return prime_list;
|
return prime_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sum(numbers: []const i32) -> i32 {
|
fn sum(numbers: []const i32) i32 {
|
||||||
var result: i32 = 0;
|
var result: i32 = 0;
|
||||||
for (numbers) |x| {
|
for (numbers) |x| {
|
||||||
result += x;
|
result += x;
|
||||||
@ -3487,7 +3487,7 @@ test "variable values" {
|
|||||||
the type <code>i32</code>. In Zig we refer to the type as <code>List(i32)</code>.
|
the type <code>i32</code>. In Zig we refer to the type as <code>List(i32)</code>.
|
||||||
</p>
|
</p>
|
||||||
{#code_begin|syntax#}
|
{#code_begin|syntax#}
|
||||||
fn List(comptime T: type) -> type {
|
fn List(comptime T: type) type {
|
||||||
return struct {
|
return struct {
|
||||||
items: []T,
|
items: []T,
|
||||||
len: usize,
|
len: usize,
|
||||||
@ -3526,7 +3526,7 @@ const warn = @import("std").debug.warn;
|
|||||||
const a_number: i32 = 1234;
|
const a_number: i32 = 1234;
|
||||||
const a_string = "foobar";
|
const a_string = "foobar";
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() void {
|
||||||
warn("here is a string: '{}' here is a number: {}\n", a_string, a_number);
|
warn("here is a string: '{}' here is a number: {}\n", a_string, a_number);
|
||||||
}
|
}
|
||||||
{#code_end#}
|
{#code_end#}
|
||||||
@ -3537,7 +3537,7 @@ pub fn main() {
|
|||||||
|
|
||||||
{#code_begin|syntax#}
|
{#code_begin|syntax#}
|
||||||
/// Calls print and then flushes the buffer.
|
/// Calls print and then flushes the buffer.
|
||||||
pub fn printf(self: &OutStream, comptime format: []const u8, args: ...) -> %void {
|
pub fn printf(self: &OutStream, comptime format: []const u8, args: ...) %void {
|
||||||
const State = enum {
|
const State = enum {
|
||||||
Start,
|
Start,
|
||||||
OpenBrace,
|
OpenBrace,
|
||||||
@ -3609,7 +3609,7 @@ pub fn printf(self: &OutStream, comptime format: []const u8, args: ...) -> %void
|
|||||||
and emits a function that actually looks like this:
|
and emits a function that actually looks like this:
|
||||||
</p>
|
</p>
|
||||||
{#code_begin|syntax#}
|
{#code_begin|syntax#}
|
||||||
pub fn printf(self: &OutStream, arg0: i32, arg1: []const u8) -> %void {
|
pub fn printf(self: &OutStream, arg0: i32, arg1: []const u8) %void {
|
||||||
try self.write("here is a string: '");
|
try self.write("here is a string: '");
|
||||||
try self.printValue(arg0);
|
try self.printValue(arg0);
|
||||||
try self.write("' here is a number: ");
|
try self.write("' here is a number: ");
|
||||||
@ -3623,7 +3623,7 @@ pub fn printf(self: &OutStream, arg0: i32, arg1: []const u8) -> %void {
|
|||||||
on the type:
|
on the type:
|
||||||
</p>
|
</p>
|
||||||
{#code_begin|syntax#}
|
{#code_begin|syntax#}
|
||||||
pub fn printValue(self: &OutStream, value: var) -> %void {
|
pub fn printValue(self: &OutStream, value: var) %void {
|
||||||
const T = @typeOf(value);
|
const T = @typeOf(value);
|
||||||
if (@isInteger(T)) {
|
if (@isInteger(T)) {
|
||||||
return self.printInt(T, value);
|
return self.printInt(T, value);
|
||||||
@ -3665,7 +3665,7 @@ const a_number: i32 = 1234;
|
|||||||
const a_string = "foobar";
|
const a_string = "foobar";
|
||||||
const fmt = "here is a string: '{}' here is a number: {}\n";
|
const fmt = "here is a string: '{}' here is a number: {}\n";
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() void {
|
||||||
warn(fmt, a_string, a_number);
|
warn(fmt, a_string, a_number);
|
||||||
}
|
}
|
||||||
{#code_end#}
|
{#code_end#}
|
||||||
@ -4101,7 +4101,7 @@ test "inline function call" {
|
|||||||
assert(@inlineCall(add, 3, 9) == 12);
|
assert(@inlineCall(add, 3, 9) == 12);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add(a: i32, b: i32) -> i32 { return a + b; }
|
fn add(a: i32, b: i32) i32 { return a + b; }
|
||||||
{#code_end#}
|
{#code_end#}
|
||||||
<p>
|
<p>
|
||||||
Unlike a normal function call, however, <code>@inlineCall</code> guarantees that the call
|
Unlike a normal function call, however, <code>@inlineCall</code> guarantees that the call
|
||||||
@ -4246,8 +4246,8 @@ fn add(a: i32, b: i32) -> i32 { a + b }</code></pre>
|
|||||||
const Derp = @OpaqueType();
|
const Derp = @OpaqueType();
|
||||||
const Wat = @OpaqueType();
|
const Wat = @OpaqueType();
|
||||||
|
|
||||||
extern fn bar(d: &Derp);
|
extern fn bar(d: &Derp) void;
|
||||||
export fn foo(w: &Wat) {
|
export fn foo(w: &Wat) void {
|
||||||
bar(w);
|
bar(w);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4552,7 +4552,7 @@ pub const TypeId = enum {
|
|||||||
{#code_begin|syntax#}
|
{#code_begin|syntax#}
|
||||||
const Builder = @import("std").build.Builder;
|
const Builder = @import("std").build.Builder;
|
||||||
|
|
||||||
pub fn build(b: &Builder) -> %void {
|
pub fn build(b: &Builder) %void {
|
||||||
const exe = b.addExecutable("example", "example.zig");
|
const exe = b.addExecutable("example", "example.zig");
|
||||||
exe.setBuildMode(b.standardReleaseOptions());
|
exe.setBuildMode(b.standardReleaseOptions());
|
||||||
b.default_step.dependOn(&exe.step);
|
b.default_step.dependOn(&exe.step);
|
||||||
@ -4612,7 +4612,7 @@ test "safety check" {
|
|||||||
comptime {
|
comptime {
|
||||||
assert(false);
|
assert(false);
|
||||||
}
|
}
|
||||||
fn assert(ok: bool) {
|
fn assert(ok: bool) void {
|
||||||
if (!ok) unreachable; // assertion failure
|
if (!ok) unreachable; // assertion failure
|
||||||
}
|
}
|
||||||
{#code_end#}
|
{#code_end#}
|
||||||
@ -4694,7 +4694,7 @@ comptime {
|
|||||||
{#code_begin|exe_err#}
|
{#code_begin|exe_err#}
|
||||||
const math = @import("std").math;
|
const math = @import("std").math;
|
||||||
const warn = @import("std").debug.warn;
|
const warn = @import("std").debug.warn;
|
||||||
pub fn main() -> %void {
|
pub fn main() %void {
|
||||||
var byte: u8 = 255;
|
var byte: u8 = 255;
|
||||||
|
|
||||||
byte = if (math.add(u8, byte, 1)) |result| result else |err| {
|
byte = if (math.add(u8, byte, 1)) |result| result else |err| {
|
||||||
@ -4722,7 +4722,7 @@ pub fn main() -> %void {
|
|||||||
</p>
|
</p>
|
||||||
{#code_begin|exe#}
|
{#code_begin|exe#}
|
||||||
const warn = @import("std").debug.warn;
|
const warn = @import("std").debug.warn;
|
||||||
pub fn main() -> %void {
|
pub fn main() %void {
|
||||||
var byte: u8 = 255;
|
var byte: u8 = 255;
|
||||||
|
|
||||||
var result: u8 = undefined;
|
var result: u8 = undefined;
|
||||||
@ -4818,7 +4818,7 @@ comptime {
|
|||||||
the <code>if</code> expression:</p>
|
the <code>if</code> expression:</p>
|
||||||
{#code_begin|exe|test#}
|
{#code_begin|exe|test#}
|
||||||
const warn = @import("std").debug.warn;
|
const warn = @import("std").debug.warn;
|
||||||
pub fn main() {
|
pub fn main() void {
|
||||||
const nullable_number: ?i32 = null;
|
const nullable_number: ?i32 = null;
|
||||||
|
|
||||||
if (nullable_number) |number| {
|
if (nullable_number) |number| {
|
||||||
@ -4838,7 +4838,7 @@ comptime {
|
|||||||
|
|
||||||
error UnableToReturnNumber;
|
error UnableToReturnNumber;
|
||||||
|
|
||||||
fn getNumberOrFail() -> %i32 {
|
fn getNumberOrFail() %i32 {
|
||||||
return error.UnableToReturnNumber;
|
return error.UnableToReturnNumber;
|
||||||
}
|
}
|
||||||
{#code_end#}
|
{#code_end#}
|
||||||
@ -4848,7 +4848,7 @@ fn getNumberOrFail() -> %i32 {
|
|||||||
{#code_begin|exe#}
|
{#code_begin|exe#}
|
||||||
const warn = @import("std").debug.warn;
|
const warn = @import("std").debug.warn;
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() void {
|
||||||
const result = getNumberOrFail();
|
const result = getNumberOrFail();
|
||||||
|
|
||||||
if (result) |number| {
|
if (result) |number| {
|
||||||
@ -4860,7 +4860,7 @@ pub fn main() {
|
|||||||
|
|
||||||
error UnableToReturnNumber;
|
error UnableToReturnNumber;
|
||||||
|
|
||||||
fn getNumberOrFail() -> %i32 {
|
fn getNumberOrFail() %i32 {
|
||||||
return error.UnableToReturnNumber;
|
return error.UnableToReturnNumber;
|
||||||
}
|
}
|
||||||
{#code_end#}
|
{#code_end#}
|
||||||
@ -5177,9 +5177,9 @@ pub const have_error_return_tracing = true;
|
|||||||
{#header_open|C String Literals#}
|
{#header_open|C String Literals#}
|
||||||
{#code_begin|exe#}
|
{#code_begin|exe#}
|
||||||
{#link_libc#}
|
{#link_libc#}
|
||||||
extern fn puts(&const u8);
|
extern fn puts(&const u8) void;
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() void {
|
||||||
puts(c"this has a null terminator");
|
puts(c"this has a null terminator");
|
||||||
puts(
|
puts(
|
||||||
c\\and so
|
c\\and so
|
||||||
@ -5202,7 +5202,7 @@ const c = @cImport({
|
|||||||
@cDefine("_NO_CRT_STDIO_INLINE", "1");
|
@cDefine("_NO_CRT_STDIO_INLINE", "1");
|
||||||
@cInclude("stdio.h");
|
@cInclude("stdio.h");
|
||||||
});
|
});
|
||||||
pub fn main() {
|
pub fn main() void {
|
||||||
_ = c.printf(c"hello\n");
|
_ = c.printf(c"hello\n");
|
||||||
}
|
}
|
||||||
{#code_end#}
|
{#code_end#}
|
||||||
@ -5237,7 +5237,7 @@ const c = @cImport({
|
|||||||
const base64 = @import("std").base64;
|
const base64 = @import("std").base64;
|
||||||
|
|
||||||
export fn decode_base_64(dest_ptr: &u8, dest_len: usize,
|
export fn decode_base_64(dest_ptr: &u8, dest_len: usize,
|
||||||
source_ptr: &const u8, source_len: usize) -> usize
|
source_ptr: &const u8, source_len: usize) usize
|
||||||
{
|
{
|
||||||
const src = source_ptr[0..source_len];
|
const src = source_ptr[0..source_len];
|
||||||
const dest = dest_ptr[0..dest_len];
|
const dest = dest_ptr[0..dest_len];
|
||||||
@ -5268,7 +5268,7 @@ int main(int argc, char **argv) {
|
|||||||
{#code_begin|syntax#}
|
{#code_begin|syntax#}
|
||||||
const Builder = @import("std").build.Builder;
|
const Builder = @import("std").build.Builder;
|
||||||
|
|
||||||
pub fn build(b: &Builder) -> %void {
|
pub fn build(b: &Builder) %void {
|
||||||
const obj = b.addObject("base64", "base64.zig");
|
const obj = b.addObject("base64", "base64.zig");
|
||||||
|
|
||||||
const exe = b.addCExecutable("test");
|
const exe = b.addCExecutable("test");
|
||||||
@ -5498,7 +5498,7 @@ const string_alias = []u8;
|
|||||||
const StructName = struct {};
|
const StructName = struct {};
|
||||||
const StructAlias = StructName;
|
const StructAlias = StructName;
|
||||||
|
|
||||||
fn functionName(param_name: TypeName) {
|
fn functionName(param_name: TypeName) void {
|
||||||
var functionPointer = functionName;
|
var functionPointer = functionName;
|
||||||
functionPointer();
|
functionPointer();
|
||||||
functionPointer = otherFunction;
|
functionPointer = otherFunction;
|
||||||
@ -5506,14 +5506,14 @@ fn functionName(param_name: TypeName) {
|
|||||||
}
|
}
|
||||||
const functionAlias = functionName;
|
const functionAlias = functionName;
|
||||||
|
|
||||||
fn ListTemplateFunction(comptime ChildType: type, comptime fixed_size: usize) -> type {
|
fn ListTemplateFunction(comptime ChildType: type, comptime fixed_size: usize) type {
|
||||||
return List(ChildType, fixed_size);
|
return List(ChildType, fixed_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ShortList(comptime T: type, comptime n: usize) -> type {
|
fn ShortList(comptime T: type, comptime n: usize) type {
|
||||||
return struct {
|
return struct {
|
||||||
field_name: [n]T,
|
field_name: [n]T,
|
||||||
fn methodName() {}
|
fn methodName() void {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5526,7 +5526,7 @@ const xml_document =
|
|||||||
const XmlParser = struct {};
|
const XmlParser = struct {};
|
||||||
|
|
||||||
// The initials BE (Big Endian) are just another word in Zig identifier names.
|
// The initials BE (Big Endian) are just another word in Zig identifier names.
|
||||||
fn readU32Be() -> u32 {}
|
fn readU32Be() u32 {}
|
||||||
{#code_end#}
|
{#code_end#}
|
||||||
<p>
|
<p>
|
||||||
See the Zig Standard Library for more examples.
|
See the Zig Standard Library for more examples.
|
||||||
@ -5558,7 +5558,7 @@ UseDecl = "use" Expression ";"
|
|||||||
|
|
||||||
ExternDecl = "extern" option(String) (FnProto | VariableDeclaration) ";"
|
ExternDecl = "extern" option(String) (FnProto | VariableDeclaration) ";"
|
||||||
|
|
||||||
FnProto = option("nakedcc" | "stdcallcc" | "extern") "fn" option(Symbol) ParamDeclList option("align" "(" Expression ")") option("section" "(" Expression ")") option("->" TypeExpr)
|
FnProto = option("nakedcc" | "stdcallcc" | "extern") "fn" option(Symbol) ParamDeclList option("align" "(" Expression ")") option("section" "(" Expression ")") TypeExpr
|
||||||
|
|
||||||
FnDef = option("inline" | "export") FnProto Block
|
FnDef = option("inline" | "export") FnProto Block
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ const os = std.os;
|
|||||||
const warn = std.debug.warn;
|
const warn = std.debug.warn;
|
||||||
const allocator = std.debug.global_allocator;
|
const allocator = std.debug.global_allocator;
|
||||||
|
|
||||||
pub fn main() -> %void {
|
pub fn main() %void {
|
||||||
var args_it = os.args();
|
var args_it = os.args();
|
||||||
const exe = try unwrapArg(??args_it.next(allocator));
|
const exe = try unwrapArg(??args_it.next(allocator));
|
||||||
var catted_anything = false;
|
var catted_anything = false;
|
||||||
@ -36,12 +36,12 @@ pub fn main() -> %void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(exe: []const u8) -> %void {
|
fn usage(exe: []const u8) %void {
|
||||||
warn("Usage: {} [FILE]...\n", exe);
|
warn("Usage: {} [FILE]...\n", exe);
|
||||||
return error.Invalid;
|
return error.Invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cat_file(stdout: &io.File, file: &io.File) -> %void {
|
fn cat_file(stdout: &io.File, file: &io.File) %void {
|
||||||
var buf: [1024 * 4]u8 = undefined;
|
var buf: [1024 * 4]u8 = undefined;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
@ -61,7 +61,7 @@ fn cat_file(stdout: &io.File, file: &io.File) -> %void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unwrapArg(arg: %[]u8) -> %[]u8 {
|
fn unwrapArg(arg: %[]u8) %[]u8 {
|
||||||
return arg catch |err| {
|
return arg catch |err| {
|
||||||
warn("Unable to parse command line: {}\n", err);
|
warn("Unable to parse command line: {}\n", err);
|
||||||
return err;
|
return err;
|
||||||
|
@ -5,7 +5,7 @@ const fmt = std.fmt;
|
|||||||
const Rand = std.rand.Rand;
|
const Rand = std.rand.Rand;
|
||||||
const os = std.os;
|
const os = std.os;
|
||||||
|
|
||||||
pub fn main() -> %void {
|
pub fn main() %void {
|
||||||
var stdout_file = try io.getStdOut();
|
var stdout_file = try io.getStdOut();
|
||||||
var stdout_file_stream = io.FileOutStream.init(&stdout_file);
|
var stdout_file_stream = io.FileOutStream.init(&stdout_file);
|
||||||
const stdout = &stdout_file_stream.stream;
|
const stdout = &stdout_file_stream.stream;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
pub fn main() -> %void {
|
pub fn main() %void {
|
||||||
// If this program is run without stdout attached, exit with an error.
|
// If this program is run without stdout attached, exit with an error.
|
||||||
var stdout_file = try std.io.getStdOut();
|
var stdout_file = try std.io.getStdOut();
|
||||||
// If this program encounters pipe failure when printing to stdout, exit
|
// If this program encounters pipe failure when printing to stdout, exit
|
||||||
|
@ -7,7 +7,7 @@ const c = @cImport({
|
|||||||
|
|
||||||
const msg = c"Hello, world!\n";
|
const msg = c"Hello, world!\n";
|
||||||
|
|
||||||
export fn main(argc: c_int, argv: &&u8) -> c_int {
|
export fn main(argc: c_int, argv: &&u8) c_int {
|
||||||
if (c.printf(msg) != c_int(c.strlen(msg)))
|
if (c.printf(msg) != c_int(c.strlen(msg)))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use @import("std").os.windows;
|
use @import("std").os.windows;
|
||||||
|
|
||||||
export fn WinMain(hInstance: HINSTANCE, hPrevInstance: HINSTANCE, lpCmdLine: PWSTR, nCmdShow: INT) -> INT {
|
export fn WinMain(hInstance: HINSTANCE, hPrevInstance: HINSTANCE, lpCmdLine: PWSTR, nCmdShow: INT) INT {
|
||||||
_ = MessageBoxA(null, c"hello", c"title", 0);
|
_ = MessageBoxA(null, c"hello", c"title", 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
const base64 = @import("std").base64;
|
const base64 = @import("std").base64;
|
||||||
|
|
||||||
export fn decode_base_64(dest_ptr: &u8, dest_len: usize, source_ptr: &const u8, source_len: usize) -> usize {
|
export fn decode_base_64(dest_ptr: &u8, dest_len: usize, source_ptr: &const u8, source_len: usize) usize {
|
||||||
const src = source_ptr[0..source_len];
|
const src = source_ptr[0..source_len];
|
||||||
const dest = dest_ptr[0..dest_len];
|
const dest = dest_ptr[0..dest_len];
|
||||||
const base64_decoder = base64.standard_decoder_unsafe;
|
const base64_decoder = base64.standard_decoder_unsafe;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
const Builder = @import("std").build.Builder;
|
const Builder = @import("std").build.Builder;
|
||||||
|
|
||||||
pub fn build(b: &Builder) -> %void {
|
pub fn build(b: &Builder) %void {
|
||||||
const obj = b.addObject("base64", "base64.zig");
|
const obj = b.addObject("base64", "base64.zig");
|
||||||
|
|
||||||
const exe = b.addCExecutable("test");
|
const exe = b.addCExecutable("test");
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
const Builder = @import("std").build.Builder;
|
const Builder = @import("std").build.Builder;
|
||||||
|
|
||||||
pub fn build(b: &Builder) -> %void {
|
pub fn build(b: &Builder) %void {
|
||||||
const lib = b.addSharedLibrary("mathtest", "mathtest.zig", b.version(1, 0, 0));
|
const lib = b.addSharedLibrary("mathtest", "mathtest.zig", b.version(1, 0, 0));
|
||||||
|
|
||||||
const exe = b.addCExecutable("test");
|
const exe = b.addCExecutable("test");
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
export fn add(a: i32, b: i32) -> i32 {
|
export fn add(a: i32, b: i32) i32 {
|
||||||
return a + b;
|
return a + b;
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ pub const Node = struct {
|
|||||||
FloatLiteral,
|
FloatLiteral,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn iterate(base: &Node, index: usize) -> ?&Node {
|
pub fn iterate(base: &Node, index: usize) ?&Node {
|
||||||
return switch (base.id) {
|
return switch (base.id) {
|
||||||
Id.Root => @fieldParentPtr(NodeRoot, "base", base).iterate(index),
|
Id.Root => @fieldParentPtr(NodeRoot, "base", base).iterate(index),
|
||||||
Id.VarDecl => @fieldParentPtr(NodeVarDecl, "base", base).iterate(index),
|
Id.VarDecl => @fieldParentPtr(NodeVarDecl, "base", base).iterate(index),
|
||||||
@ -35,7 +35,7 @@ pub const Node = struct {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn destroy(base: &Node, allocator: &mem.Allocator) {
|
pub fn destroy(base: &Node, allocator: &mem.Allocator) void {
|
||||||
return switch (base.id) {
|
return switch (base.id) {
|
||||||
Id.Root => allocator.destroy(@fieldParentPtr(NodeRoot, "base", base)),
|
Id.Root => allocator.destroy(@fieldParentPtr(NodeRoot, "base", base)),
|
||||||
Id.VarDecl => allocator.destroy(@fieldParentPtr(NodeVarDecl, "base", base)),
|
Id.VarDecl => allocator.destroy(@fieldParentPtr(NodeVarDecl, "base", base)),
|
||||||
@ -55,7 +55,7 @@ pub const NodeRoot = struct {
|
|||||||
base: Node,
|
base: Node,
|
||||||
decls: ArrayList(&Node),
|
decls: ArrayList(&Node),
|
||||||
|
|
||||||
pub fn iterate(self: &NodeRoot, index: usize) -> ?&Node {
|
pub fn iterate(self: &NodeRoot, index: usize) ?&Node {
|
||||||
if (index < self.decls.len) {
|
if (index < self.decls.len) {
|
||||||
return self.decls.items[self.decls.len - index - 1];
|
return self.decls.items[self.decls.len - index - 1];
|
||||||
}
|
}
|
||||||
@ -76,7 +76,7 @@ pub const NodeVarDecl = struct {
|
|||||||
align_node: ?&Node,
|
align_node: ?&Node,
|
||||||
init_node: ?&Node,
|
init_node: ?&Node,
|
||||||
|
|
||||||
pub fn iterate(self: &NodeVarDecl, index: usize) -> ?&Node {
|
pub fn iterate(self: &NodeVarDecl, index: usize) ?&Node {
|
||||||
var i = index;
|
var i = index;
|
||||||
|
|
||||||
if (self.type_node) |type_node| {
|
if (self.type_node) |type_node| {
|
||||||
@ -102,7 +102,7 @@ pub const NodeIdentifier = struct {
|
|||||||
base: Node,
|
base: Node,
|
||||||
name_token: Token,
|
name_token: Token,
|
||||||
|
|
||||||
pub fn iterate(self: &NodeIdentifier, index: usize) -> ?&Node {
|
pub fn iterate(self: &NodeIdentifier, index: usize) ?&Node {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -113,7 +113,7 @@ pub const NodeFnProto = struct {
|
|||||||
fn_token: Token,
|
fn_token: Token,
|
||||||
name_token: ?Token,
|
name_token: ?Token,
|
||||||
params: ArrayList(&Node),
|
params: ArrayList(&Node),
|
||||||
return_type: ?&Node,
|
return_type: &Node,
|
||||||
var_args_token: ?Token,
|
var_args_token: ?Token,
|
||||||
extern_token: ?Token,
|
extern_token: ?Token,
|
||||||
inline_token: ?Token,
|
inline_token: ?Token,
|
||||||
@ -122,7 +122,7 @@ pub const NodeFnProto = struct {
|
|||||||
lib_name: ?&Node, // populated if this is an extern declaration
|
lib_name: ?&Node, // populated if this is an extern declaration
|
||||||
align_expr: ?&Node, // populated if align(A) is present
|
align_expr: ?&Node, // populated if align(A) is present
|
||||||
|
|
||||||
pub fn iterate(self: &NodeFnProto, index: usize) -> ?&Node {
|
pub fn iterate(self: &NodeFnProto, index: usize) ?&Node {
|
||||||
var i = index;
|
var i = index;
|
||||||
|
|
||||||
if (self.body_node) |body_node| {
|
if (self.body_node) |body_node| {
|
||||||
@ -130,10 +130,8 @@ pub const NodeFnProto = struct {
|
|||||||
i -= 1;
|
i -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self.return_type) |return_type| {
|
if (i < 1) return self.return_type;
|
||||||
if (i < 1) return return_type;
|
i -= 1;
|
||||||
i -= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (self.align_expr) |align_expr| {
|
if (self.align_expr) |align_expr| {
|
||||||
if (i < 1) return align_expr;
|
if (i < 1) return align_expr;
|
||||||
@ -160,7 +158,7 @@ pub const NodeParamDecl = struct {
|
|||||||
type_node: &Node,
|
type_node: &Node,
|
||||||
var_args_token: ?Token,
|
var_args_token: ?Token,
|
||||||
|
|
||||||
pub fn iterate(self: &NodeParamDecl, index: usize) -> ?&Node {
|
pub fn iterate(self: &NodeParamDecl, index: usize) ?&Node {
|
||||||
var i = index;
|
var i = index;
|
||||||
|
|
||||||
if (i < 1) return self.type_node;
|
if (i < 1) return self.type_node;
|
||||||
@ -176,7 +174,7 @@ pub const NodeBlock = struct {
|
|||||||
end_token: Token,
|
end_token: Token,
|
||||||
statements: ArrayList(&Node),
|
statements: ArrayList(&Node),
|
||||||
|
|
||||||
pub fn iterate(self: &NodeBlock, index: usize) -> ?&Node {
|
pub fn iterate(self: &NodeBlock, index: usize) ?&Node {
|
||||||
var i = index;
|
var i = index;
|
||||||
|
|
||||||
if (i < self.statements.len) return self.statements.items[i];
|
if (i < self.statements.len) return self.statements.items[i];
|
||||||
@ -198,7 +196,7 @@ pub const NodeInfixOp = struct {
|
|||||||
BangEqual,
|
BangEqual,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn iterate(self: &NodeInfixOp, index: usize) -> ?&Node {
|
pub fn iterate(self: &NodeInfixOp, index: usize) ?&Node {
|
||||||
var i = index;
|
var i = index;
|
||||||
|
|
||||||
if (i < 1) return self.lhs;
|
if (i < 1) return self.lhs;
|
||||||
@ -234,7 +232,7 @@ pub const NodePrefixOp = struct {
|
|||||||
volatile_token: ?Token,
|
volatile_token: ?Token,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn iterate(self: &NodePrefixOp, index: usize) -> ?&Node {
|
pub fn iterate(self: &NodePrefixOp, index: usize) ?&Node {
|
||||||
var i = index;
|
var i = index;
|
||||||
|
|
||||||
switch (self.op) {
|
switch (self.op) {
|
||||||
@ -258,7 +256,7 @@ pub const NodeIntegerLiteral = struct {
|
|||||||
base: Node,
|
base: Node,
|
||||||
token: Token,
|
token: Token,
|
||||||
|
|
||||||
pub fn iterate(self: &NodeIntegerLiteral, index: usize) -> ?&Node {
|
pub fn iterate(self: &NodeIntegerLiteral, index: usize) ?&Node {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -267,7 +265,7 @@ pub const NodeFloatLiteral = struct {
|
|||||||
base: Node,
|
base: Node,
|
||||||
token: Token,
|
token: Token,
|
||||||
|
|
||||||
pub fn iterate(self: &NodeFloatLiteral, index: usize) -> ?&Node {
|
pub fn iterate(self: &NodeFloatLiteral, index: usize) ?&Node {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -7,7 +7,7 @@ pub const ModuleRef = removeNullability(c.LLVMModuleRef);
|
|||||||
pub const ContextRef = removeNullability(c.LLVMContextRef);
|
pub const ContextRef = removeNullability(c.LLVMContextRef);
|
||||||
pub const BuilderRef = removeNullability(c.LLVMBuilderRef);
|
pub const BuilderRef = removeNullability(c.LLVMBuilderRef);
|
||||||
|
|
||||||
fn removeNullability(comptime T: type) -> type {
|
fn removeNullability(comptime T: type) type {
|
||||||
comptime assert(@typeId(T) == builtin.TypeId.Nullable);
|
comptime assert(@typeId(T) == builtin.TypeId.Nullable);
|
||||||
return T.Child;
|
return T.Child;
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ error ZigInstallationNotFound;
|
|||||||
|
|
||||||
const default_zig_cache_name = "zig-cache";
|
const default_zig_cache_name = "zig-cache";
|
||||||
|
|
||||||
pub fn main() -> %void {
|
pub fn main() %void {
|
||||||
main2() catch |err| {
|
main2() catch |err| {
|
||||||
if (err != error.InvalidCommandLineArguments) {
|
if (err != error.InvalidCommandLineArguments) {
|
||||||
warn("{}\n", @errorName(err));
|
warn("{}\n", @errorName(err));
|
||||||
@ -39,7 +39,7 @@ const Cmd = enum {
|
|||||||
Targets,
|
Targets,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn badArgs(comptime format: []const u8, args: ...) -> error {
|
fn badArgs(comptime format: []const u8, args: ...) error {
|
||||||
var stderr = try io.getStdErr();
|
var stderr = try io.getStdErr();
|
||||||
var stderr_stream_adapter = io.FileOutStream.init(&stderr);
|
var stderr_stream_adapter = io.FileOutStream.init(&stderr);
|
||||||
const stderr_stream = &stderr_stream_adapter.stream;
|
const stderr_stream = &stderr_stream_adapter.stream;
|
||||||
@ -48,7 +48,7 @@ fn badArgs(comptime format: []const u8, args: ...) -> error {
|
|||||||
return error.InvalidCommandLineArguments;
|
return error.InvalidCommandLineArguments;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn main2() -> %void {
|
pub fn main2() %void {
|
||||||
const allocator = std.heap.c_allocator;
|
const allocator = std.heap.c_allocator;
|
||||||
|
|
||||||
const args = try os.argsAlloc(allocator);
|
const args = try os.argsAlloc(allocator);
|
||||||
@ -472,7 +472,7 @@ pub fn main2() -> %void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn printUsage(stream: &io.OutStream) -> %void {
|
fn printUsage(stream: &io.OutStream) %void {
|
||||||
try stream.write(
|
try stream.write(
|
||||||
\\Usage: zig [command] [options]
|
\\Usage: zig [command] [options]
|
||||||
\\
|
\\
|
||||||
@ -548,7 +548,7 @@ fn printUsage(stream: &io.OutStream) -> %void {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn printZen() -> %void {
|
fn printZen() %void {
|
||||||
var stdout_file = try io.getStdErr();
|
var stdout_file = try io.getStdErr();
|
||||||
try stdout_file.write(
|
try stdout_file.write(
|
||||||
\\
|
\\
|
||||||
@ -569,7 +569,7 @@ fn printZen() -> %void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Caller must free result
|
/// Caller must free result
|
||||||
fn resolveZigLibDir(allocator: &mem.Allocator, zig_install_prefix_arg: ?[]const u8) -> %[]u8 {
|
fn resolveZigLibDir(allocator: &mem.Allocator, zig_install_prefix_arg: ?[]const u8) %[]u8 {
|
||||||
if (zig_install_prefix_arg) |zig_install_prefix| {
|
if (zig_install_prefix_arg) |zig_install_prefix| {
|
||||||
return testZigInstallPrefix(allocator, zig_install_prefix) catch |err| {
|
return testZigInstallPrefix(allocator, zig_install_prefix) catch |err| {
|
||||||
warn("No Zig installation found at prefix {}: {}\n", zig_install_prefix_arg, @errorName(err));
|
warn("No Zig installation found at prefix {}: {}\n", zig_install_prefix_arg, @errorName(err));
|
||||||
@ -585,7 +585,7 @@ fn resolveZigLibDir(allocator: &mem.Allocator, zig_install_prefix_arg: ?[]const
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Caller must free result
|
/// Caller must free result
|
||||||
fn testZigInstallPrefix(allocator: &mem.Allocator, test_path: []const u8) -> %[]u8 {
|
fn testZigInstallPrefix(allocator: &mem.Allocator, test_path: []const u8) %[]u8 {
|
||||||
const test_zig_dir = try os.path.join(allocator, test_path, "lib", "zig");
|
const test_zig_dir = try os.path.join(allocator, test_path, "lib", "zig");
|
||||||
errdefer allocator.free(test_zig_dir);
|
errdefer allocator.free(test_zig_dir);
|
||||||
|
|
||||||
@ -599,7 +599,7 @@ fn testZigInstallPrefix(allocator: &mem.Allocator, test_path: []const u8) -> %[]
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Caller must free result
|
/// Caller must free result
|
||||||
fn findZigLibDir(allocator: &mem.Allocator) -> %[]u8 {
|
fn findZigLibDir(allocator: &mem.Allocator) %[]u8 {
|
||||||
const self_exe_path = try os.selfExeDirPath(allocator);
|
const self_exe_path = try os.selfExeDirPath(allocator);
|
||||||
defer allocator.free(self_exe_path);
|
defer allocator.free(self_exe_path);
|
||||||
|
|
||||||
|
@ -110,7 +110,7 @@ pub const Module = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub fn create(allocator: &mem.Allocator, name: []const u8, root_src_path: ?[]const u8, target: &const Target,
|
pub fn create(allocator: &mem.Allocator, name: []const u8, root_src_path: ?[]const u8, target: &const Target,
|
||||||
kind: Kind, build_mode: builtin.Mode, zig_lib_dir: []const u8, cache_dir: []const u8) -> %&Module
|
kind: Kind, build_mode: builtin.Mode, zig_lib_dir: []const u8, cache_dir: []const u8) %&Module
|
||||||
{
|
{
|
||||||
var name_buffer = try Buffer.init(allocator, name);
|
var name_buffer = try Buffer.init(allocator, name);
|
||||||
errdefer name_buffer.deinit();
|
errdefer name_buffer.deinit();
|
||||||
@ -185,11 +185,11 @@ pub const Module = struct {
|
|||||||
return module_ptr;
|
return module_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dump(self: &Module) {
|
fn dump(self: &Module) void {
|
||||||
c.LLVMDumpModule(self.module);
|
c.LLVMDumpModule(self.module);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn destroy(self: &Module) {
|
pub fn destroy(self: &Module) void {
|
||||||
c.LLVMDisposeBuilder(self.builder);
|
c.LLVMDisposeBuilder(self.builder);
|
||||||
c.LLVMDisposeModule(self.module);
|
c.LLVMDisposeModule(self.module);
|
||||||
c.LLVMContextDispose(self.context);
|
c.LLVMContextDispose(self.context);
|
||||||
@ -198,7 +198,7 @@ pub const Module = struct {
|
|||||||
self.allocator.destroy(self);
|
self.allocator.destroy(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build(self: &Module) -> %void {
|
pub fn build(self: &Module) %void {
|
||||||
if (self.llvm_argv.len != 0) {
|
if (self.llvm_argv.len != 0) {
|
||||||
var c_compatible_args = try std.cstr.NullTerminated2DArray.fromSlices(self.allocator,
|
var c_compatible_args = try std.cstr.NullTerminated2DArray.fromSlices(self.allocator,
|
||||||
[][]const []const u8 { [][]const u8{"zig (LLVM option parsing)"}, self.llvm_argv, });
|
[][]const []const u8 { [][]const u8{"zig (LLVM option parsing)"}, self.llvm_argv, });
|
||||||
@ -244,16 +244,16 @@ pub const Module = struct {
|
|||||||
var parser = Parser.init(&tokenizer, self.allocator, root_src_real_path);
|
var parser = Parser.init(&tokenizer, self.allocator, root_src_real_path);
|
||||||
defer parser.deinit();
|
defer parser.deinit();
|
||||||
|
|
||||||
const root_node = try parser.parse();
|
const tree = try parser.parse();
|
||||||
defer parser.freeAst(root_node);
|
defer tree.deinit();
|
||||||
|
|
||||||
var stderr_file = try std.io.getStdErr();
|
var stderr_file = try std.io.getStdErr();
|
||||||
var stderr_file_out_stream = std.io.FileOutStream.init(&stderr_file);
|
var stderr_file_out_stream = std.io.FileOutStream.init(&stderr_file);
|
||||||
const out_stream = &stderr_file_out_stream.stream;
|
const out_stream = &stderr_file_out_stream.stream;
|
||||||
try parser.renderAst(out_stream, root_node);
|
try parser.renderAst(out_stream, tree.root_node);
|
||||||
|
|
||||||
warn("====fmt:====\n");
|
warn("====fmt:====\n");
|
||||||
try parser.renderSource(out_stream, root_node);
|
try parser.renderSource(out_stream, tree.root_node);
|
||||||
|
|
||||||
warn("====ir:====\n");
|
warn("====ir:====\n");
|
||||||
warn("TODO\n\n");
|
warn("TODO\n\n");
|
||||||
@ -263,11 +263,11 @@ pub const Module = struct {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn link(self: &Module, out_file: ?[]const u8) -> %void {
|
pub fn link(self: &Module, out_file: ?[]const u8) %void {
|
||||||
warn("TODO link");
|
warn("TODO link");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addLinkLib(self: &Module, name: []const u8, provided_explicitly: bool) -> %&LinkLib {
|
pub fn addLinkLib(self: &Module, name: []const u8, provided_explicitly: bool) %&LinkLib {
|
||||||
const is_libc = mem.eql(u8, name, "c");
|
const is_libc = mem.eql(u8, name, "c");
|
||||||
|
|
||||||
if (is_libc) {
|
if (is_libc) {
|
||||||
@ -297,7 +297,7 @@ pub const Module = struct {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
fn printError(comptime format: []const u8, args: ...) -> %void {
|
fn printError(comptime format: []const u8, args: ...) %void {
|
||||||
var stderr_file = try std.io.getStdErr();
|
var stderr_file = try std.io.getStdErr();
|
||||||
var stderr_file_out_stream = std.io.FileOutStream.init(&stderr_file);
|
var stderr_file_out_stream = std.io.FileOutStream.init(&stderr_file);
|
||||||
const out_stream = &stderr_file_out_stream.stream;
|
const out_stream = &stderr_file_out_stream.stream;
|
||||||
|
@ -20,14 +20,25 @@ pub const Parser = struct {
|
|||||||
put_back_tokens: [2]Token,
|
put_back_tokens: [2]Token,
|
||||||
put_back_count: usize,
|
put_back_count: usize,
|
||||||
source_file_name: []const u8,
|
source_file_name: []const u8,
|
||||||
cleanup_root_node: ?&ast.NodeRoot,
|
|
||||||
|
pub const Tree = struct {
|
||||||
|
root_node: &ast.NodeRoot,
|
||||||
|
|
||||||
|
pub fn deinit(self: &const Tree) void {
|
||||||
|
// TODO free the whole arena
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// This memory contents are used only during a function call. It's used to repurpose memory;
|
// This memory contents are used only during a function call. It's used to repurpose memory;
|
||||||
// specifically so that freeAst can be guaranteed to succeed.
|
// we reuse the same bytes for the stack data structure used by parsing, tree rendering, and
|
||||||
|
// source rendering.
|
||||||
const utility_bytes_align = @alignOf( union { a: RenderAstFrame, b: State, c: RenderState } );
|
const utility_bytes_align = @alignOf( union { a: RenderAstFrame, b: State, c: RenderState } );
|
||||||
utility_bytes: []align(utility_bytes_align) u8,
|
utility_bytes: []align(utility_bytes_align) u8,
|
||||||
|
|
||||||
pub fn init(tokenizer: &Tokenizer, allocator: &mem.Allocator, source_file_name: []const u8) -> Parser {
|
/// `allocator` should be an arena allocator. Parser never calls free on anything. After you're
|
||||||
|
/// done with a Parser, free the arena. After the arena is freed, no member functions of Parser
|
||||||
|
/// may be called.
|
||||||
|
pub fn init(tokenizer: &Tokenizer, allocator: &mem.Allocator, source_file_name: []const u8) Parser {
|
||||||
return Parser {
|
return Parser {
|
||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
.tokenizer = tokenizer,
|
.tokenizer = tokenizer,
|
||||||
@ -35,12 +46,10 @@ pub const Parser = struct {
|
|||||||
.put_back_count = 0,
|
.put_back_count = 0,
|
||||||
.source_file_name = source_file_name,
|
.source_file_name = source_file_name,
|
||||||
.utility_bytes = []align(utility_bytes_align) u8{},
|
.utility_bytes = []align(utility_bytes_align) u8{},
|
||||||
.cleanup_root_node = null,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: &Parser) {
|
pub fn deinit(self: &Parser) void {
|
||||||
assert(self.cleanup_root_node == null);
|
|
||||||
self.allocator.free(self.utility_bytes);
|
self.allocator.free(self.utility_bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,7 +63,7 @@ pub const Parser = struct {
|
|||||||
NullableField: &?&ast.Node,
|
NullableField: &?&ast.Node,
|
||||||
List: &ArrayList(&ast.Node),
|
List: &ArrayList(&ast.Node),
|
||||||
|
|
||||||
pub fn store(self: &const DestPtr, value: &ast.Node) -> %void {
|
pub fn store(self: &const DestPtr, value: &ast.Node) %void {
|
||||||
switch (*self) {
|
switch (*self) {
|
||||||
DestPtr.Field => |ptr| *ptr = value,
|
DestPtr.Field => |ptr| *ptr = value,
|
||||||
DestPtr.NullableField => |ptr| *ptr = value,
|
DestPtr.NullableField => |ptr| *ptr = value,
|
||||||
@ -88,52 +97,16 @@ pub const Parser = struct {
|
|||||||
Statement: &ast.NodeBlock,
|
Statement: &ast.NodeBlock,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn freeAst(self: &Parser, root_node: &ast.NodeRoot) {
|
/// Returns an AST tree, allocated with the parser's allocator.
|
||||||
// utility_bytes is big enough to do this iteration since we were able to do
|
/// Result should be freed with `freeAst` when done.
|
||||||
// the parsing in the first place
|
pub fn parse(self: &Parser) %Tree {
|
||||||
comptime assert(@sizeOf(State) >= @sizeOf(&ast.Node));
|
|
||||||
|
|
||||||
var stack = self.initUtilityArrayList(&ast.Node);
|
|
||||||
defer self.deinitUtilityArrayList(stack);
|
|
||||||
|
|
||||||
stack.append(&root_node.base) catch unreachable;
|
|
||||||
while (stack.popOrNull()) |node| {
|
|
||||||
var i: usize = 0;
|
|
||||||
while (node.iterate(i)) |child| : (i += 1) {
|
|
||||||
if (child.iterate(0) != null) {
|
|
||||||
stack.append(child) catch unreachable;
|
|
||||||
} else {
|
|
||||||
child.destroy(self.allocator);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
node.destroy(self.allocator);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parse(self: &Parser) -> %&ast.NodeRoot {
|
|
||||||
const result = self.parseInner() catch |err| x: {
|
|
||||||
if (self.cleanup_root_node) |root_node| {
|
|
||||||
self.freeAst(root_node);
|
|
||||||
}
|
|
||||||
break :x err;
|
|
||||||
};
|
|
||||||
self.cleanup_root_node = null;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parseInner(self: &Parser) -> %&ast.NodeRoot {
|
|
||||||
var stack = self.initUtilityArrayList(State);
|
var stack = self.initUtilityArrayList(State);
|
||||||
defer self.deinitUtilityArrayList(stack);
|
defer self.deinitUtilityArrayList(stack);
|
||||||
|
|
||||||
const root_node = x: {
|
const root_node = try self.createRoot();
|
||||||
const root_node = try self.createRoot();
|
// TODO errdefer arena free root node
|
||||||
errdefer self.allocator.destroy(root_node);
|
|
||||||
// This stack append has to succeed for freeAst to work
|
try stack.append(State.TopLevel);
|
||||||
try stack.append(State.TopLevel);
|
|
||||||
break :x root_node;
|
|
||||||
};
|
|
||||||
assert(self.cleanup_root_node == null);
|
|
||||||
self.cleanup_root_node = root_node;
|
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
//{
|
//{
|
||||||
@ -159,7 +132,7 @@ pub const Parser = struct {
|
|||||||
stack.append(State { .TopLevelExtern = token }) catch unreachable;
|
stack.append(State { .TopLevelExtern = token }) catch unreachable;
|
||||||
continue;
|
continue;
|
||||||
},
|
},
|
||||||
Token.Id.Eof => return root_node,
|
Token.Id.Eof => return Tree {.root_node = root_node},
|
||||||
else => {
|
else => {
|
||||||
self.putBackToken(token);
|
self.putBackToken(token);
|
||||||
// TODO shouldn't need this cast
|
// TODO shouldn't need this cast
|
||||||
@ -439,15 +412,11 @@ pub const Parser = struct {
|
|||||||
if (token.id == Token.Id.Keyword_align) {
|
if (token.id == Token.Id.Keyword_align) {
|
||||||
@panic("TODO fn proto align");
|
@panic("TODO fn proto align");
|
||||||
}
|
}
|
||||||
if (token.id == Token.Id.Arrow) {
|
self.putBackToken(token);
|
||||||
stack.append(State {
|
stack.append(State {
|
||||||
.TypeExpr = DestPtr {.NullableField = &fn_proto.return_type},
|
.TypeExpr = DestPtr {.Field = &fn_proto.return_type},
|
||||||
}) catch unreachable;
|
}) catch unreachable;
|
||||||
continue;
|
continue;
|
||||||
} else {
|
|
||||||
self.putBackToken(token);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
State.ParamDecl => |fn_proto| {
|
State.ParamDecl => |fn_proto| {
|
||||||
@ -575,9 +544,8 @@ pub const Parser = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn createRoot(self: &Parser) -> %&ast.NodeRoot {
|
fn createRoot(self: &Parser) %&ast.NodeRoot {
|
||||||
const node = try self.allocator.create(ast.NodeRoot);
|
const node = try self.allocator.create(ast.NodeRoot);
|
||||||
errdefer self.allocator.destroy(node);
|
|
||||||
|
|
||||||
*node = ast.NodeRoot {
|
*node = ast.NodeRoot {
|
||||||
.base = ast.Node {.id = ast.Node.Id.Root},
|
.base = ast.Node {.id = ast.Node.Id.Root},
|
||||||
@ -587,10 +555,9 @@ pub const Parser = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn createVarDecl(self: &Parser, visib_token: &const ?Token, mut_token: &const Token, comptime_token: &const ?Token,
|
fn createVarDecl(self: &Parser, visib_token: &const ?Token, mut_token: &const Token, comptime_token: &const ?Token,
|
||||||
extern_token: &const ?Token) -> %&ast.NodeVarDecl
|
extern_token: &const ?Token) %&ast.NodeVarDecl
|
||||||
{
|
{
|
||||||
const node = try self.allocator.create(ast.NodeVarDecl);
|
const node = try self.allocator.create(ast.NodeVarDecl);
|
||||||
errdefer self.allocator.destroy(node);
|
|
||||||
|
|
||||||
*node = ast.NodeVarDecl {
|
*node = ast.NodeVarDecl {
|
||||||
.base = ast.Node {.id = ast.Node.Id.VarDecl},
|
.base = ast.Node {.id = ast.Node.Id.VarDecl},
|
||||||
@ -610,10 +577,9 @@ pub const Parser = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn createFnProto(self: &Parser, fn_token: &const Token, extern_token: &const ?Token,
|
fn createFnProto(self: &Parser, fn_token: &const Token, extern_token: &const ?Token,
|
||||||
cc_token: &const ?Token, visib_token: &const ?Token, inline_token: &const ?Token) -> %&ast.NodeFnProto
|
cc_token: &const ?Token, visib_token: &const ?Token, inline_token: &const ?Token) %&ast.NodeFnProto
|
||||||
{
|
{
|
||||||
const node = try self.allocator.create(ast.NodeFnProto);
|
const node = try self.allocator.create(ast.NodeFnProto);
|
||||||
errdefer self.allocator.destroy(node);
|
|
||||||
|
|
||||||
*node = ast.NodeFnProto {
|
*node = ast.NodeFnProto {
|
||||||
.base = ast.Node {.id = ast.Node.Id.FnProto},
|
.base = ast.Node {.id = ast.Node.Id.FnProto},
|
||||||
@ -621,7 +587,7 @@ pub const Parser = struct {
|
|||||||
.name_token = null,
|
.name_token = null,
|
||||||
.fn_token = *fn_token,
|
.fn_token = *fn_token,
|
||||||
.params = ArrayList(&ast.Node).init(self.allocator),
|
.params = ArrayList(&ast.Node).init(self.allocator),
|
||||||
.return_type = null,
|
.return_type = undefined,
|
||||||
.var_args_token = null,
|
.var_args_token = null,
|
||||||
.extern_token = *extern_token,
|
.extern_token = *extern_token,
|
||||||
.inline_token = *inline_token,
|
.inline_token = *inline_token,
|
||||||
@ -633,9 +599,8 @@ pub const Parser = struct {
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn createParamDecl(self: &Parser) -> %&ast.NodeParamDecl {
|
fn createParamDecl(self: &Parser) %&ast.NodeParamDecl {
|
||||||
const node = try self.allocator.create(ast.NodeParamDecl);
|
const node = try self.allocator.create(ast.NodeParamDecl);
|
||||||
errdefer self.allocator.destroy(node);
|
|
||||||
|
|
||||||
*node = ast.NodeParamDecl {
|
*node = ast.NodeParamDecl {
|
||||||
.base = ast.Node {.id = ast.Node.Id.ParamDecl},
|
.base = ast.Node {.id = ast.Node.Id.ParamDecl},
|
||||||
@ -648,9 +613,8 @@ pub const Parser = struct {
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn createBlock(self: &Parser, begin_token: &const Token) -> %&ast.NodeBlock {
|
fn createBlock(self: &Parser, begin_token: &const Token) %&ast.NodeBlock {
|
||||||
const node = try self.allocator.create(ast.NodeBlock);
|
const node = try self.allocator.create(ast.NodeBlock);
|
||||||
errdefer self.allocator.destroy(node);
|
|
||||||
|
|
||||||
*node = ast.NodeBlock {
|
*node = ast.NodeBlock {
|
||||||
.base = ast.Node {.id = ast.Node.Id.Block},
|
.base = ast.Node {.id = ast.Node.Id.Block},
|
||||||
@ -661,9 +625,8 @@ pub const Parser = struct {
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn createInfixOp(self: &Parser, op_token: &const Token, op: &const ast.NodeInfixOp.InfixOp) -> %&ast.NodeInfixOp {
|
fn createInfixOp(self: &Parser, op_token: &const Token, op: &const ast.NodeInfixOp.InfixOp) %&ast.NodeInfixOp {
|
||||||
const node = try self.allocator.create(ast.NodeInfixOp);
|
const node = try self.allocator.create(ast.NodeInfixOp);
|
||||||
errdefer self.allocator.destroy(node);
|
|
||||||
|
|
||||||
*node = ast.NodeInfixOp {
|
*node = ast.NodeInfixOp {
|
||||||
.base = ast.Node {.id = ast.Node.Id.InfixOp},
|
.base = ast.Node {.id = ast.Node.Id.InfixOp},
|
||||||
@ -675,9 +638,8 @@ pub const Parser = struct {
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn createPrefixOp(self: &Parser, op_token: &const Token, op: &const ast.NodePrefixOp.PrefixOp) -> %&ast.NodePrefixOp {
|
fn createPrefixOp(self: &Parser, op_token: &const Token, op: &const ast.NodePrefixOp.PrefixOp) %&ast.NodePrefixOp {
|
||||||
const node = try self.allocator.create(ast.NodePrefixOp);
|
const node = try self.allocator.create(ast.NodePrefixOp);
|
||||||
errdefer self.allocator.destroy(node);
|
|
||||||
|
|
||||||
*node = ast.NodePrefixOp {
|
*node = ast.NodePrefixOp {
|
||||||
.base = ast.Node {.id = ast.Node.Id.PrefixOp},
|
.base = ast.Node {.id = ast.Node.Id.PrefixOp},
|
||||||
@ -688,9 +650,8 @@ pub const Parser = struct {
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn createIdentifier(self: &Parser, name_token: &const Token) -> %&ast.NodeIdentifier {
|
fn createIdentifier(self: &Parser, name_token: &const Token) %&ast.NodeIdentifier {
|
||||||
const node = try self.allocator.create(ast.NodeIdentifier);
|
const node = try self.allocator.create(ast.NodeIdentifier);
|
||||||
errdefer self.allocator.destroy(node);
|
|
||||||
|
|
||||||
*node = ast.NodeIdentifier {
|
*node = ast.NodeIdentifier {
|
||||||
.base = ast.Node {.id = ast.Node.Id.Identifier},
|
.base = ast.Node {.id = ast.Node.Id.Identifier},
|
||||||
@ -699,9 +660,8 @@ pub const Parser = struct {
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn createIntegerLiteral(self: &Parser, token: &const Token) -> %&ast.NodeIntegerLiteral {
|
fn createIntegerLiteral(self: &Parser, token: &const Token) %&ast.NodeIntegerLiteral {
|
||||||
const node = try self.allocator.create(ast.NodeIntegerLiteral);
|
const node = try self.allocator.create(ast.NodeIntegerLiteral);
|
||||||
errdefer self.allocator.destroy(node);
|
|
||||||
|
|
||||||
*node = ast.NodeIntegerLiteral {
|
*node = ast.NodeIntegerLiteral {
|
||||||
.base = ast.Node {.id = ast.Node.Id.IntegerLiteral},
|
.base = ast.Node {.id = ast.Node.Id.IntegerLiteral},
|
||||||
@ -710,9 +670,8 @@ pub const Parser = struct {
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn createFloatLiteral(self: &Parser, token: &const Token) -> %&ast.NodeFloatLiteral {
|
fn createFloatLiteral(self: &Parser, token: &const Token) %&ast.NodeFloatLiteral {
|
||||||
const node = try self.allocator.create(ast.NodeFloatLiteral);
|
const node = try self.allocator.create(ast.NodeFloatLiteral);
|
||||||
errdefer self.allocator.destroy(node);
|
|
||||||
|
|
||||||
*node = ast.NodeFloatLiteral {
|
*node = ast.NodeFloatLiteral {
|
||||||
.base = ast.Node {.id = ast.Node.Id.FloatLiteral},
|
.base = ast.Node {.id = ast.Node.Id.FloatLiteral},
|
||||||
@ -721,40 +680,36 @@ pub const Parser = struct {
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn createAttachIdentifier(self: &Parser, dest_ptr: &const DestPtr, name_token: &const Token) -> %&ast.NodeIdentifier {
|
fn createAttachIdentifier(self: &Parser, dest_ptr: &const DestPtr, name_token: &const Token) %&ast.NodeIdentifier {
|
||||||
const node = try self.createIdentifier(name_token);
|
const node = try self.createIdentifier(name_token);
|
||||||
errdefer self.allocator.destroy(node);
|
|
||||||
try dest_ptr.store(&node.base);
|
try dest_ptr.store(&node.base);
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn createAttachParamDecl(self: &Parser, list: &ArrayList(&ast.Node)) -> %&ast.NodeParamDecl {
|
fn createAttachParamDecl(self: &Parser, list: &ArrayList(&ast.Node)) %&ast.NodeParamDecl {
|
||||||
const node = try self.createParamDecl();
|
const node = try self.createParamDecl();
|
||||||
errdefer self.allocator.destroy(node);
|
|
||||||
try list.append(&node.base);
|
try list.append(&node.base);
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn createAttachFnProto(self: &Parser, list: &ArrayList(&ast.Node), fn_token: &const Token,
|
fn createAttachFnProto(self: &Parser, list: &ArrayList(&ast.Node), fn_token: &const Token,
|
||||||
extern_token: &const ?Token, cc_token: &const ?Token, visib_token: &const ?Token,
|
extern_token: &const ?Token, cc_token: &const ?Token, visib_token: &const ?Token,
|
||||||
inline_token: &const ?Token) -> %&ast.NodeFnProto
|
inline_token: &const ?Token) %&ast.NodeFnProto
|
||||||
{
|
{
|
||||||
const node = try self.createFnProto(fn_token, extern_token, cc_token, visib_token, inline_token);
|
const node = try self.createFnProto(fn_token, extern_token, cc_token, visib_token, inline_token);
|
||||||
errdefer self.allocator.destroy(node);
|
|
||||||
try list.append(&node.base);
|
try list.append(&node.base);
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn createAttachVarDecl(self: &Parser, list: &ArrayList(&ast.Node), visib_token: &const ?Token,
|
fn createAttachVarDecl(self: &Parser, list: &ArrayList(&ast.Node), visib_token: &const ?Token,
|
||||||
mut_token: &const Token, comptime_token: &const ?Token, extern_token: &const ?Token) -> %&ast.NodeVarDecl
|
mut_token: &const Token, comptime_token: &const ?Token, extern_token: &const ?Token) %&ast.NodeVarDecl
|
||||||
{
|
{
|
||||||
const node = try self.createVarDecl(visib_token, mut_token, comptime_token, extern_token);
|
const node = try self.createVarDecl(visib_token, mut_token, comptime_token, extern_token);
|
||||||
errdefer self.allocator.destroy(node);
|
|
||||||
try list.append(&node.base);
|
try list.append(&node.base);
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parseError(self: &Parser, token: &const Token, comptime fmt: []const u8, args: ...) -> error {
|
fn parseError(self: &Parser, token: &const Token, comptime fmt: []const u8, args: ...) error {
|
||||||
const loc = self.tokenizer.getTokenLocation(token);
|
const loc = self.tokenizer.getTokenLocation(token);
|
||||||
warn("{}:{}:{}: error: " ++ fmt ++ "\n", self.source_file_name, loc.line + 1, loc.column + 1, args);
|
warn("{}:{}:{}: error: " ++ fmt ++ "\n", self.source_file_name, loc.line + 1, loc.column + 1, args);
|
||||||
warn("{}\n", self.tokenizer.buffer[loc.line_start..loc.line_end]);
|
warn("{}\n", self.tokenizer.buffer[loc.line_start..loc.line_end]);
|
||||||
@ -775,24 +730,24 @@ pub const Parser = struct {
|
|||||||
return error.ParseError;
|
return error.ParseError;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expectToken(self: &Parser, token: &const Token, id: @TagType(Token.Id)) -> %void {
|
fn expectToken(self: &Parser, token: &const Token, id: @TagType(Token.Id)) %void {
|
||||||
if (token.id != id) {
|
if (token.id != id) {
|
||||||
return self.parseError(token, "expected {}, found {}", @tagName(id), @tagName(token.id));
|
return self.parseError(token, "expected {}, found {}", @tagName(id), @tagName(token.id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eatToken(self: &Parser, id: @TagType(Token.Id)) -> %Token {
|
fn eatToken(self: &Parser, id: @TagType(Token.Id)) %Token {
|
||||||
const token = self.getNextToken();
|
const token = self.getNextToken();
|
||||||
try self.expectToken(token, id);
|
try self.expectToken(token, id);
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn putBackToken(self: &Parser, token: &const Token) {
|
fn putBackToken(self: &Parser, token: &const Token) void {
|
||||||
self.put_back_tokens[self.put_back_count] = *token;
|
self.put_back_tokens[self.put_back_count] = *token;
|
||||||
self.put_back_count += 1;
|
self.put_back_count += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getNextToken(self: &Parser) -> Token {
|
fn getNextToken(self: &Parser) Token {
|
||||||
if (self.put_back_count != 0) {
|
if (self.put_back_count != 0) {
|
||||||
const put_back_index = self.put_back_count - 1;
|
const put_back_index = self.put_back_count - 1;
|
||||||
const put_back_token = self.put_back_tokens[put_back_index];
|
const put_back_token = self.put_back_tokens[put_back_index];
|
||||||
@ -808,7 +763,7 @@ pub const Parser = struct {
|
|||||||
indent: usize,
|
indent: usize,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn renderAst(self: &Parser, stream: &std.io.OutStream, root_node: &ast.NodeRoot) -> %void {
|
pub fn renderAst(self: &Parser, stream: &std.io.OutStream, root_node: &ast.NodeRoot) %void {
|
||||||
var stack = self.initUtilityArrayList(RenderAstFrame);
|
var stack = self.initUtilityArrayList(RenderAstFrame);
|
||||||
defer self.deinitUtilityArrayList(stack);
|
defer self.deinitUtilityArrayList(stack);
|
||||||
|
|
||||||
@ -847,7 +802,7 @@ pub const Parser = struct {
|
|||||||
Indent: usize,
|
Indent: usize,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn renderSource(self: &Parser, stream: &std.io.OutStream, root_node: &ast.NodeRoot) -> %void {
|
pub fn renderSource(self: &Parser, stream: &std.io.OutStream, root_node: &ast.NodeRoot) %void {
|
||||||
var stack = self.initUtilityArrayList(RenderState);
|
var stack = self.initUtilityArrayList(RenderState);
|
||||||
defer self.deinitUtilityArrayList(stack);
|
defer self.deinitUtilityArrayList(stack);
|
||||||
|
|
||||||
@ -1039,14 +994,12 @@ pub const Parser = struct {
|
|||||||
if (fn_proto.align_expr != null) {
|
if (fn_proto.align_expr != null) {
|
||||||
@panic("TODO");
|
@panic("TODO");
|
||||||
}
|
}
|
||||||
if (fn_proto.return_type) |return_type| {
|
try stream.print(" ");
|
||||||
try stream.print(" -> ");
|
if (fn_proto.body_node) |body_node| {
|
||||||
if (fn_proto.body_node) |body_node| {
|
try stack.append(RenderState { .Expression = body_node});
|
||||||
try stack.append(RenderState { .Expression = body_node});
|
try stack.append(RenderState { .Text = " "});
|
||||||
try stack.append(RenderState { .Text = " "});
|
|
||||||
}
|
|
||||||
try stack.append(RenderState { .Expression = return_type});
|
|
||||||
}
|
}
|
||||||
|
try stack.append(RenderState { .Expression = fn_proto.return_type});
|
||||||
},
|
},
|
||||||
RenderState.Statement => |base| {
|
RenderState.Statement => |base| {
|
||||||
switch (base.id) {
|
switch (base.id) {
|
||||||
@ -1066,7 +1019,7 @@ pub const Parser = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn initUtilityArrayList(self: &Parser, comptime T: type) -> ArrayList(T) {
|
fn initUtilityArrayList(self: &Parser, comptime T: type) ArrayList(T) {
|
||||||
const new_byte_count = self.utility_bytes.len - self.utility_bytes.len % @sizeOf(T);
|
const new_byte_count = self.utility_bytes.len - self.utility_bytes.len % @sizeOf(T);
|
||||||
self.utility_bytes = self.allocator.alignedShrink(u8, utility_bytes_align, self.utility_bytes, new_byte_count);
|
self.utility_bytes = self.allocator.alignedShrink(u8, utility_bytes_align, self.utility_bytes, new_byte_count);
|
||||||
const typed_slice = ([]T)(self.utility_bytes);
|
const typed_slice = ([]T)(self.utility_bytes);
|
||||||
@ -1077,7 +1030,7 @@ pub const Parser = struct {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deinitUtilityArrayList(self: &Parser, list: var) {
|
fn deinitUtilityArrayList(self: &Parser, list: var) void {
|
||||||
self.utility_bytes = ([]align(utility_bytes_align) u8)(list.items);
|
self.utility_bytes = ([]align(utility_bytes_align) u8)(list.items);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1085,7 +1038,7 @@ pub const Parser = struct {
|
|||||||
|
|
||||||
var fixed_buffer_mem: [100 * 1024]u8 = undefined;
|
var fixed_buffer_mem: [100 * 1024]u8 = undefined;
|
||||||
|
|
||||||
fn testParse(source: []const u8, allocator: &mem.Allocator) -> %[]u8 {
|
fn testParse(source: []const u8, allocator: &mem.Allocator) %[]u8 {
|
||||||
var padded_source: [0x100]u8 = undefined;
|
var padded_source: [0x100]u8 = undefined;
|
||||||
std.mem.copy(u8, padded_source[0..source.len], source);
|
std.mem.copy(u8, padded_source[0..source.len], source);
|
||||||
padded_source[source.len + 0] = '\n';
|
padded_source[source.len + 0] = '\n';
|
||||||
@ -1096,30 +1049,34 @@ fn testParse(source: []const u8, allocator: &mem.Allocator) -> %[]u8 {
|
|||||||
var parser = Parser.init(&tokenizer, allocator, "(memory buffer)");
|
var parser = Parser.init(&tokenizer, allocator, "(memory buffer)");
|
||||||
defer parser.deinit();
|
defer parser.deinit();
|
||||||
|
|
||||||
const root_node = try parser.parse();
|
const tree = try parser.parse();
|
||||||
defer parser.freeAst(root_node);
|
defer tree.deinit();
|
||||||
|
|
||||||
var buffer = try std.Buffer.initSize(allocator, 0);
|
var buffer = try std.Buffer.initSize(allocator, 0);
|
||||||
var buffer_out_stream = io.BufferOutStream.init(&buffer);
|
var buffer_out_stream = io.BufferOutStream.init(&buffer);
|
||||||
try parser.renderSource(&buffer_out_stream.stream, root_node);
|
try parser.renderSource(&buffer_out_stream.stream, tree.root_node);
|
||||||
return buffer.toOwnedSlice();
|
return buffer.toOwnedSlice();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
error TestFailed;
|
||||||
|
error NondeterministicMemoryUsage;
|
||||||
|
error MemoryLeakDetected;
|
||||||
|
|
||||||
// TODO test for memory leaks
|
// TODO test for memory leaks
|
||||||
// TODO test for valid frees
|
// TODO test for valid frees
|
||||||
fn testCanonical(source: []const u8) {
|
fn testCanonical(source: []const u8) %void {
|
||||||
const needed_alloc_count = x: {
|
const needed_alloc_count = x: {
|
||||||
// Try it once with unlimited memory, make sure it works
|
// Try it once with unlimited memory, make sure it works
|
||||||
var fixed_allocator = mem.FixedBufferAllocator.init(fixed_buffer_mem[0..]);
|
var fixed_allocator = mem.FixedBufferAllocator.init(fixed_buffer_mem[0..]);
|
||||||
var failing_allocator = std.debug.FailingAllocator.init(&fixed_allocator.allocator, @maxValue(usize));
|
var failing_allocator = std.debug.FailingAllocator.init(&fixed_allocator.allocator, @maxValue(usize));
|
||||||
const result_source = testParse(source, &failing_allocator.allocator) catch @panic("test failed");
|
const result_source = try testParse(source, &failing_allocator.allocator);
|
||||||
if (!mem.eql(u8, result_source, source)) {
|
if (!mem.eql(u8, result_source, source)) {
|
||||||
warn("\n====== expected this output: =========\n");
|
warn("\n====== expected this output: =========\n");
|
||||||
warn("{}", source);
|
warn("{}", source);
|
||||||
warn("\n======== instead found this: =========\n");
|
warn("\n======== instead found this: =========\n");
|
||||||
warn("{}", result_source);
|
warn("{}", result_source);
|
||||||
warn("\n======================================\n");
|
warn("\n======================================\n");
|
||||||
@panic("test failed");
|
return error.TestFailed;
|
||||||
}
|
}
|
||||||
failing_allocator.allocator.free(result_source);
|
failing_allocator.allocator.free(result_source);
|
||||||
break :x failing_allocator.index;
|
break :x failing_allocator.index;
|
||||||
@ -1130,7 +1087,7 @@ fn testCanonical(source: []const u8) {
|
|||||||
var fixed_allocator = mem.FixedBufferAllocator.init(fixed_buffer_mem[0..]);
|
var fixed_allocator = mem.FixedBufferAllocator.init(fixed_buffer_mem[0..]);
|
||||||
var failing_allocator = std.debug.FailingAllocator.init(&fixed_allocator.allocator, fail_index);
|
var failing_allocator = std.debug.FailingAllocator.init(&fixed_allocator.allocator, fail_index);
|
||||||
if (testParse(source, &failing_allocator.allocator)) |_| {
|
if (testParse(source, &failing_allocator.allocator)) |_| {
|
||||||
@panic("non-deterministic memory usage");
|
return error.NondeterministicMemoryUsage;
|
||||||
} else |err| {
|
} else |err| {
|
||||||
assert(err == error.OutOfMemory);
|
assert(err == error.OutOfMemory);
|
||||||
// TODO make this pass
|
// TODO make this pass
|
||||||
@ -1139,19 +1096,19 @@ fn testCanonical(source: []const u8) {
|
|||||||
// fail_index, needed_alloc_count,
|
// fail_index, needed_alloc_count,
|
||||||
// failing_allocator.allocated_bytes, failing_allocator.freed_bytes,
|
// failing_allocator.allocated_bytes, failing_allocator.freed_bytes,
|
||||||
// failing_allocator.index, failing_allocator.deallocations);
|
// failing_allocator.index, failing_allocator.deallocations);
|
||||||
// @panic("memory leak detected");
|
// return error.MemoryLeakDetected;
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
test "zig fmt" {
|
test "zig fmt" {
|
||||||
testCanonical(
|
try testCanonical(
|
||||||
\\extern fn puts(s: &const u8) -> c_int;
|
\\extern fn puts(s: &const u8) c_int;
|
||||||
\\
|
\\
|
||||||
);
|
);
|
||||||
|
|
||||||
testCanonical(
|
try testCanonical(
|
||||||
\\const a = b;
|
\\const a = b;
|
||||||
\\pub const a = b;
|
\\pub const a = b;
|
||||||
\\var a = b;
|
\\var a = b;
|
||||||
@ -1163,44 +1120,44 @@ test "zig fmt" {
|
|||||||
\\
|
\\
|
||||||
);
|
);
|
||||||
|
|
||||||
testCanonical(
|
try testCanonical(
|
||||||
\\extern var foo: c_int;
|
\\extern var foo: c_int;
|
||||||
\\
|
\\
|
||||||
);
|
);
|
||||||
|
|
||||||
testCanonical(
|
try testCanonical(
|
||||||
\\var foo: c_int align(1);
|
\\var foo: c_int align(1);
|
||||||
\\
|
\\
|
||||||
);
|
);
|
||||||
|
|
||||||
testCanonical(
|
try testCanonical(
|
||||||
\\fn main(argc: c_int, argv: &&u8) -> c_int {
|
\\fn main(argc: c_int, argv: &&u8) c_int {
|
||||||
\\ const a = b;
|
\\ const a = b;
|
||||||
\\}
|
\\}
|
||||||
\\
|
\\
|
||||||
);
|
);
|
||||||
|
|
||||||
testCanonical(
|
try testCanonical(
|
||||||
\\fn foo(argc: c_int, argv: &&u8) -> c_int {
|
\\fn foo(argc: c_int, argv: &&u8) c_int {
|
||||||
\\ return 0;
|
\\ return 0;
|
||||||
\\}
|
\\}
|
||||||
\\
|
\\
|
||||||
);
|
);
|
||||||
|
|
||||||
testCanonical(
|
try testCanonical(
|
||||||
\\extern fn f1(s: &align(&u8) u8) -> c_int;
|
\\extern fn f1(s: &align(&u8) u8) c_int;
|
||||||
\\
|
\\
|
||||||
);
|
);
|
||||||
|
|
||||||
testCanonical(
|
try testCanonical(
|
||||||
\\extern fn f1(s: &&align(1) &const &volatile u8) -> c_int;
|
\\extern fn f1(s: &&align(1) &const &volatile u8) c_int;
|
||||||
\\extern fn f2(s: &align(1) const &align(1) volatile &const volatile u8) -> c_int;
|
\\extern fn f2(s: &align(1) const &align(1) volatile &const volatile u8) c_int;
|
||||||
\\extern fn f3(s: &align(1) const volatile u8) -> c_int;
|
\\extern fn f3(s: &align(1) const volatile u8) c_int;
|
||||||
\\
|
\\
|
||||||
);
|
);
|
||||||
|
|
||||||
testCanonical(
|
try testCanonical(
|
||||||
\\fn f1(a: bool, b: bool) -> bool {
|
\\fn f1(a: bool, b: bool) bool {
|
||||||
\\ a != b;
|
\\ a != b;
|
||||||
\\ return a == b;
|
\\ return a == b;
|
||||||
\\}
|
\\}
|
||||||
|
@ -11,7 +11,7 @@ pub const Target = union(enum) {
|
|||||||
Native,
|
Native,
|
||||||
Cross: CrossTarget,
|
Cross: CrossTarget,
|
||||||
|
|
||||||
pub fn oFileExt(self: &const Target) -> []const u8 {
|
pub fn oFileExt(self: &const Target) []const u8 {
|
||||||
const environ = switch (*self) {
|
const environ = switch (*self) {
|
||||||
Target.Native => builtin.environ,
|
Target.Native => builtin.environ,
|
||||||
Target.Cross => |t| t.environ,
|
Target.Cross => |t| t.environ,
|
||||||
@ -22,28 +22,28 @@ pub const Target = union(enum) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn exeFileExt(self: &const Target) -> []const u8 {
|
pub fn exeFileExt(self: &const Target) []const u8 {
|
||||||
return switch (self.getOs()) {
|
return switch (self.getOs()) {
|
||||||
builtin.Os.windows => ".exe",
|
builtin.Os.windows => ".exe",
|
||||||
else => "",
|
else => "",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getOs(self: &const Target) -> builtin.Os {
|
pub fn getOs(self: &const Target) builtin.Os {
|
||||||
return switch (*self) {
|
return switch (*self) {
|
||||||
Target.Native => builtin.os,
|
Target.Native => builtin.os,
|
||||||
Target.Cross => |t| t.os,
|
Target.Cross => |t| t.os,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn isDarwin(self: &const Target) -> bool {
|
pub fn isDarwin(self: &const Target) bool {
|
||||||
return switch (self.getOs()) {
|
return switch (self.getOs()) {
|
||||||
builtin.Os.ios, builtin.Os.macosx => true,
|
builtin.Os.ios, builtin.Os.macosx => true,
|
||||||
else => false,
|
else => false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn isWindows(self: &const Target) -> bool {
|
pub fn isWindows(self: &const Target) bool {
|
||||||
return switch (self.getOs()) {
|
return switch (self.getOs()) {
|
||||||
builtin.Os.windows => true,
|
builtin.Os.windows => true,
|
||||||
else => false,
|
else => false,
|
||||||
@ -51,7 +51,7 @@ pub const Target = union(enum) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn initializeAll() {
|
pub fn initializeAll() void {
|
||||||
c.LLVMInitializeAllTargets();
|
c.LLVMInitializeAllTargets();
|
||||||
c.LLVMInitializeAllTargetInfos();
|
c.LLVMInitializeAllTargetInfos();
|
||||||
c.LLVMInitializeAllTargetMCs();
|
c.LLVMInitializeAllTargetMCs();
|
||||||
|
@ -53,7 +53,7 @@ pub const Token = struct {
|
|||||||
KeywordId{.bytes="while", .id = Id.Keyword_while},
|
KeywordId{.bytes="while", .id = Id.Keyword_while},
|
||||||
};
|
};
|
||||||
|
|
||||||
fn getKeyword(bytes: []const u8) -> ?Id {
|
fn getKeyword(bytes: []const u8) ?Id {
|
||||||
for (keywords) |kw| {
|
for (keywords) |kw| {
|
||||||
if (mem.eql(u8, kw.bytes, bytes)) {
|
if (mem.eql(u8, kw.bytes, bytes)) {
|
||||||
return kw.id;
|
return kw.id;
|
||||||
@ -146,7 +146,7 @@ pub const Tokenizer = struct {
|
|||||||
line_end: usize,
|
line_end: usize,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn getTokenLocation(self: &Tokenizer, token: &const Token) -> Location {
|
pub fn getTokenLocation(self: &Tokenizer, token: &const Token) Location {
|
||||||
var loc = Location {
|
var loc = Location {
|
||||||
.line = 0,
|
.line = 0,
|
||||||
.column = 0,
|
.column = 0,
|
||||||
@ -171,13 +171,13 @@ pub const Tokenizer = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// For debugging purposes
|
/// For debugging purposes
|
||||||
pub fn dump(self: &Tokenizer, token: &const Token) {
|
pub fn dump(self: &Tokenizer, token: &const Token) void {
|
||||||
std.debug.warn("{} \"{}\"\n", @tagName(token.id), self.buffer[token.start..token.end]);
|
std.debug.warn("{} \"{}\"\n", @tagName(token.id), self.buffer[token.start..token.end]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// buffer must end with "\n\n\n". This is so that attempting to decode
|
/// buffer must end with "\n\n\n". This is so that attempting to decode
|
||||||
/// a the 3 trailing bytes of a 4-byte utf8 sequence is never a buffer overflow.
|
/// a the 3 trailing bytes of a 4-byte utf8 sequence is never a buffer overflow.
|
||||||
pub fn init(buffer: []const u8) -> Tokenizer {
|
pub fn init(buffer: []const u8) Tokenizer {
|
||||||
std.debug.assert(buffer[buffer.len - 1] == '\n');
|
std.debug.assert(buffer[buffer.len - 1] == '\n');
|
||||||
std.debug.assert(buffer[buffer.len - 2] == '\n');
|
std.debug.assert(buffer[buffer.len - 2] == '\n');
|
||||||
std.debug.assert(buffer[buffer.len - 3] == '\n');
|
std.debug.assert(buffer[buffer.len - 3] == '\n');
|
||||||
@ -212,7 +212,7 @@ pub const Tokenizer = struct {
|
|||||||
Period2,
|
Period2,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn next(self: &Tokenizer) -> Token {
|
pub fn next(self: &Tokenizer) Token {
|
||||||
if (self.pending_invalid_token) |token| {
|
if (self.pending_invalid_token) |token| {
|
||||||
self.pending_invalid_token = null;
|
self.pending_invalid_token = null;
|
||||||
return token;
|
return token;
|
||||||
@ -528,11 +528,11 @@ pub const Tokenizer = struct {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getTokenSlice(self: &const Tokenizer, token: &const Token) -> []const u8 {
|
pub fn getTokenSlice(self: &const Tokenizer, token: &const Token) []const u8 {
|
||||||
return self.buffer[token.start..token.end];
|
return self.buffer[token.start..token.end];
|
||||||
}
|
}
|
||||||
|
|
||||||
fn checkLiteralCharacter(self: &Tokenizer) {
|
fn checkLiteralCharacter(self: &Tokenizer) void {
|
||||||
if (self.pending_invalid_token != null) return;
|
if (self.pending_invalid_token != null) return;
|
||||||
const invalid_length = self.getInvalidCharacterLength();
|
const invalid_length = self.getInvalidCharacterLength();
|
||||||
if (invalid_length == 0) return;
|
if (invalid_length == 0) return;
|
||||||
@ -543,7 +543,7 @@ pub const Tokenizer = struct {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getInvalidCharacterLength(self: &Tokenizer) -> u3 {
|
fn getInvalidCharacterLength(self: &Tokenizer) u3 {
|
||||||
const c0 = self.buffer[self.index];
|
const c0 = self.buffer[self.index];
|
||||||
if (c0 < 0x80) {
|
if (c0 < 0x80) {
|
||||||
if (c0 < 0x20 or c0 == 0x7f) {
|
if (c0 < 0x20 or c0 == 0x7f) {
|
||||||
@ -636,7 +636,7 @@ test "tokenizer - illegal unicode codepoints" {
|
|||||||
testTokenize("//\xe2\x80\xaa", []Token.Id{});
|
testTokenize("//\xe2\x80\xaa", []Token.Id{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn testTokenize(source: []const u8, expected_tokens: []const Token.Id) {
|
fn testTokenize(source: []const u8, expected_tokens: []const Token.Id) void {
|
||||||
// (test authors, just make this bigger if you need it)
|
// (test authors, just make this bigger if you need it)
|
||||||
var padded_source: [0x100]u8 = undefined;
|
var padded_source: [0x100]u8 = undefined;
|
||||||
std.mem.copy(u8, padded_source[0..source.len], source);
|
std.mem.copy(u8, padded_source[0..source.len], source);
|
||||||
|
@ -918,9 +918,7 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
|
|||||||
if (fn_type_id->alignment != 0) {
|
if (fn_type_id->alignment != 0) {
|
||||||
buf_appendf(&fn_type->name, " align(%" PRIu32 ")", fn_type_id->alignment);
|
buf_appendf(&fn_type->name, " align(%" PRIu32 ")", fn_type_id->alignment);
|
||||||
}
|
}
|
||||||
if (fn_type_id->return_type->id != TypeTableEntryIdVoid) {
|
buf_appendf(&fn_type->name, " %s", buf_ptr(&fn_type_id->return_type->name));
|
||||||
buf_appendf(&fn_type->name, " -> %s", buf_ptr(&fn_type_id->return_type->name));
|
|
||||||
}
|
|
||||||
skip_debug_info = skip_debug_info || !fn_type_id->return_type->di_type;
|
skip_debug_info = skip_debug_info || !fn_type_id->return_type->di_type;
|
||||||
|
|
||||||
// next, loop over the parameters again and compute debug information
|
// next, loop over the parameters again and compute debug information
|
||||||
@ -1082,7 +1080,7 @@ TypeTableEntry *get_generic_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
|
|||||||
const char *comma_str = (i == 0) ? "" : ",";
|
const char *comma_str = (i == 0) ? "" : ",";
|
||||||
buf_appendf(&fn_type->name, "%svar", comma_str);
|
buf_appendf(&fn_type->name, "%svar", comma_str);
|
||||||
}
|
}
|
||||||
buf_appendf(&fn_type->name, ")->var");
|
buf_appendf(&fn_type->name, ")var");
|
||||||
|
|
||||||
fn_type->data.fn.fn_type_id = *fn_type_id;
|
fn_type->data.fn.fn_type_id = *fn_type_id;
|
||||||
fn_type->data.fn.is_generic = true;
|
fn_type->data.fn.is_generic = true;
|
||||||
@ -2665,7 +2663,7 @@ static bool scope_is_root_decls(Scope *scope) {
|
|||||||
|
|
||||||
static void wrong_panic_prototype(CodeGen *g, AstNode *proto_node, TypeTableEntry *fn_type) {
|
static void wrong_panic_prototype(CodeGen *g, AstNode *proto_node, TypeTableEntry *fn_type) {
|
||||||
add_node_error(g, proto_node,
|
add_node_error(g, proto_node,
|
||||||
buf_sprintf("expected 'fn([]const u8, ?&builtin.StackTrace) -> unreachable', found '%s'",
|
buf_sprintf("expected 'fn([]const u8, ?&builtin.StackTrace) unreachable', found '%s'",
|
||||||
buf_ptr(&fn_type->name)));
|
buf_ptr(&fn_type->name)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -450,10 +450,9 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
AstNode *return_type_node = node->data.fn_proto.return_type;
|
AstNode *return_type_node = node->data.fn_proto.return_type;
|
||||||
if (return_type_node != nullptr) {
|
assert(return_type_node != nullptr);
|
||||||
fprintf(ar->f, " -> ");
|
fprintf(ar->f, " ");
|
||||||
render_node_grouped(ar, return_type_node);
|
render_node_grouped(ar, return_type_node);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NodeTypeFnDef:
|
case NodeTypeFnDef:
|
||||||
|
@ -84,11 +84,6 @@ static AstNode *ast_create_node(ParseContext *pc, NodeType type, Token *first_to
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
static AstNode *ast_create_void_type_node(ParseContext *pc, Token *token) {
|
|
||||||
AstNode *node = ast_create_node(pc, NodeTypeSymbol, token);
|
|
||||||
node->data.symbol_expr.symbol = pc->void_buf;
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void parse_asm_template(ParseContext *pc, AstNode *node) {
|
static void parse_asm_template(ParseContext *pc, AstNode *node) {
|
||||||
Buf *asm_template = node->data.asm_expr.asm_template;
|
Buf *asm_template = node->data.asm_expr.asm_template;
|
||||||
@ -2245,7 +2240,7 @@ static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mand
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
FnProto = option("nakedcc" | "stdcallcc" | "extern") "fn" option(Symbol) ParamDeclList option("align" "(" Expression ")") option("section" "(" Expression ")") option("->" TypeExpr)
|
FnProto = option("nakedcc" | "stdcallcc" | "extern") "fn" option(Symbol) ParamDeclList option("align" "(" Expression ")") option("section" "(" Expression ")") TypeExpr
|
||||||
*/
|
*/
|
||||||
static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool mandatory, VisibMod visib_mod) {
|
static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool mandatory, VisibMod visib_mod) {
|
||||||
Token *first_token = &pc->tokens->at(*token_index);
|
Token *first_token = &pc->tokens->at(*token_index);
|
||||||
@ -2320,12 +2315,7 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool m
|
|||||||
ast_eat_token(pc, token_index, TokenIdRParen);
|
ast_eat_token(pc, token_index, TokenIdRParen);
|
||||||
next_token = &pc->tokens->at(*token_index);
|
next_token = &pc->tokens->at(*token_index);
|
||||||
}
|
}
|
||||||
if (next_token->id == TokenIdArrow) {
|
node->data.fn_proto.return_type = ast_parse_type_expr(pc, token_index, true);
|
||||||
*token_index += 1;
|
|
||||||
node->data.fn_proto.return_type = ast_parse_type_expr(pc, token_index, false);
|
|
||||||
} else {
|
|
||||||
node->data.fn_proto.return_type = ast_create_void_type_node(pc, next_token);
|
|
||||||
}
|
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
@ -920,7 +920,7 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou
|
|||||||
// void foo(void) -> Foo;
|
// void foo(void) -> Foo;
|
||||||
// we want to keep the return type AST node.
|
// we want to keep the return type AST node.
|
||||||
if (is_c_void_type(proto_node->data.fn_proto.return_type)) {
|
if (is_c_void_type(proto_node->data.fn_proto.return_type)) {
|
||||||
proto_node->data.fn_proto.return_type = nullptr;
|
proto_node->data.fn_proto.return_type = trans_create_node_symbol_str(c, "void");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,11 +4,11 @@ const assert = debug.assert;
|
|||||||
const mem = std.mem;
|
const mem = std.mem;
|
||||||
const Allocator = mem.Allocator;
|
const Allocator = mem.Allocator;
|
||||||
|
|
||||||
pub fn ArrayList(comptime T: type) -> type {
|
pub fn ArrayList(comptime T: type) type {
|
||||||
return AlignedArrayList(T, @alignOf(T));
|
return AlignedArrayList(T, @alignOf(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn AlignedArrayList(comptime T: type, comptime A: u29) -> type{
|
pub fn AlignedArrayList(comptime T: type, comptime A: u29) type{
|
||||||
return struct {
|
return struct {
|
||||||
const Self = this;
|
const Self = this;
|
||||||
|
|
||||||
@ -20,7 +20,7 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) -> type{
|
|||||||
allocator: &Allocator,
|
allocator: &Allocator,
|
||||||
|
|
||||||
/// Deinitialize with `deinit` or use `toOwnedSlice`.
|
/// Deinitialize with `deinit` or use `toOwnedSlice`.
|
||||||
pub fn init(allocator: &Allocator) -> Self {
|
pub fn init(allocator: &Allocator) Self {
|
||||||
return Self {
|
return Self {
|
||||||
.items = []align(A) T{},
|
.items = []align(A) T{},
|
||||||
.len = 0,
|
.len = 0,
|
||||||
@ -28,22 +28,22 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) -> type{
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(l: &Self) {
|
pub fn deinit(l: &Self) void {
|
||||||
l.allocator.free(l.items);
|
l.allocator.free(l.items);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn toSlice(l: &Self) -> []align(A) T {
|
pub fn toSlice(l: &Self) []align(A) T {
|
||||||
return l.items[0..l.len];
|
return l.items[0..l.len];
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn toSliceConst(l: &const Self) -> []align(A) const T {
|
pub fn toSliceConst(l: &const Self) []align(A) const T {
|
||||||
return l.items[0..l.len];
|
return l.items[0..l.len];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ArrayList takes ownership of the passed in slice. The slice must have been
|
/// ArrayList takes ownership of the passed in slice. The slice must have been
|
||||||
/// allocated with `allocator`.
|
/// allocated with `allocator`.
|
||||||
/// Deinitialize with `deinit` or use `toOwnedSlice`.
|
/// Deinitialize with `deinit` or use `toOwnedSlice`.
|
||||||
pub fn fromOwnedSlice(allocator: &Allocator, slice: []align(A) T) -> Self {
|
pub fn fromOwnedSlice(allocator: &Allocator, slice: []align(A) T) Self {
|
||||||
return Self {
|
return Self {
|
||||||
.items = slice,
|
.items = slice,
|
||||||
.len = slice.len,
|
.len = slice.len,
|
||||||
@ -52,35 +52,35 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) -> type{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The caller owns the returned memory. ArrayList becomes empty.
|
/// The caller owns the returned memory. ArrayList becomes empty.
|
||||||
pub fn toOwnedSlice(self: &Self) -> []align(A) T {
|
pub fn toOwnedSlice(self: &Self) []align(A) T {
|
||||||
const allocator = self.allocator;
|
const allocator = self.allocator;
|
||||||
const result = allocator.alignedShrink(T, A, self.items, self.len);
|
const result = allocator.alignedShrink(T, A, self.items, self.len);
|
||||||
*self = init(allocator);
|
*self = init(allocator);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn append(l: &Self, item: &const T) -> %void {
|
pub fn append(l: &Self, item: &const T) %void {
|
||||||
const new_item_ptr = try l.addOne();
|
const new_item_ptr = try l.addOne();
|
||||||
*new_item_ptr = *item;
|
*new_item_ptr = *item;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn appendSlice(l: &Self, items: []align(A) const T) -> %void {
|
pub fn appendSlice(l: &Self, items: []align(A) const T) %void {
|
||||||
try l.ensureCapacity(l.len + items.len);
|
try l.ensureCapacity(l.len + items.len);
|
||||||
mem.copy(T, l.items[l.len..], items);
|
mem.copy(T, l.items[l.len..], items);
|
||||||
l.len += items.len;
|
l.len += items.len;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resize(l: &Self, new_len: usize) -> %void {
|
pub fn resize(l: &Self, new_len: usize) %void {
|
||||||
try l.ensureCapacity(new_len);
|
try l.ensureCapacity(new_len);
|
||||||
l.len = new_len;
|
l.len = new_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn shrink(l: &Self, new_len: usize) {
|
pub fn shrink(l: &Self, new_len: usize) void {
|
||||||
assert(new_len <= l.len);
|
assert(new_len <= l.len);
|
||||||
l.len = new_len;
|
l.len = new_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ensureCapacity(l: &Self, new_capacity: usize) -> %void {
|
pub fn ensureCapacity(l: &Self, new_capacity: usize) %void {
|
||||||
var better_capacity = l.items.len;
|
var better_capacity = l.items.len;
|
||||||
if (better_capacity >= new_capacity) return;
|
if (better_capacity >= new_capacity) return;
|
||||||
while (true) {
|
while (true) {
|
||||||
@ -90,7 +90,7 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) -> type{
|
|||||||
l.items = try l.allocator.alignedRealloc(T, A, l.items, better_capacity);
|
l.items = try l.allocator.alignedRealloc(T, A, l.items, better_capacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addOne(l: &Self) -> %&T {
|
pub fn addOne(l: &Self) %&T {
|
||||||
const new_length = l.len + 1;
|
const new_length = l.len + 1;
|
||||||
try l.ensureCapacity(new_length);
|
try l.ensureCapacity(new_length);
|
||||||
const result = &l.items[l.len];
|
const result = &l.items[l.len];
|
||||||
@ -98,12 +98,12 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) -> type{
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pop(self: &Self) -> T {
|
pub fn pop(self: &Self) T {
|
||||||
self.len -= 1;
|
self.len -= 1;
|
||||||
return self.items[self.len];
|
return self.items[self.len];
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn popOrNull(self: &Self) -> ?T {
|
pub fn popOrNull(self: &Self) ?T {
|
||||||
if (self.len == 0)
|
if (self.len == 0)
|
||||||
return null;
|
return null;
|
||||||
return self.pop();
|
return self.pop();
|
||||||
|
@ -11,7 +11,7 @@ pub const Base64Encoder = struct {
|
|||||||
pad_char: u8,
|
pad_char: u8,
|
||||||
|
|
||||||
/// a bunch of assertions, then simply pass the data right through.
|
/// a bunch of assertions, then simply pass the data right through.
|
||||||
pub fn init(alphabet_chars: []const u8, pad_char: u8) -> Base64Encoder {
|
pub fn init(alphabet_chars: []const u8, pad_char: u8) Base64Encoder {
|
||||||
assert(alphabet_chars.len == 64);
|
assert(alphabet_chars.len == 64);
|
||||||
var char_in_alphabet = []bool{false} ** 256;
|
var char_in_alphabet = []bool{false} ** 256;
|
||||||
for (alphabet_chars) |c| {
|
for (alphabet_chars) |c| {
|
||||||
@ -27,12 +27,12 @@ pub const Base64Encoder = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// ceil(source_len * 4/3)
|
/// ceil(source_len * 4/3)
|
||||||
pub fn calcSize(source_len: usize) -> usize {
|
pub fn calcSize(source_len: usize) usize {
|
||||||
return @divTrunc(source_len + 2, 3) * 4;
|
return @divTrunc(source_len + 2, 3) * 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// dest.len must be what you get from ::calcSize.
|
/// dest.len must be what you get from ::calcSize.
|
||||||
pub fn encode(encoder: &const Base64Encoder, dest: []u8, source: []const u8) {
|
pub fn encode(encoder: &const Base64Encoder, dest: []u8, source: []const u8) void {
|
||||||
assert(dest.len == Base64Encoder.calcSize(source.len));
|
assert(dest.len == Base64Encoder.calcSize(source.len));
|
||||||
|
|
||||||
var i: usize = 0;
|
var i: usize = 0;
|
||||||
@ -90,7 +90,7 @@ pub const Base64Decoder = struct {
|
|||||||
char_in_alphabet: [256]bool,
|
char_in_alphabet: [256]bool,
|
||||||
pad_char: u8,
|
pad_char: u8,
|
||||||
|
|
||||||
pub fn init(alphabet_chars: []const u8, pad_char: u8) -> Base64Decoder {
|
pub fn init(alphabet_chars: []const u8, pad_char: u8) Base64Decoder {
|
||||||
assert(alphabet_chars.len == 64);
|
assert(alphabet_chars.len == 64);
|
||||||
|
|
||||||
var result = Base64Decoder{
|
var result = Base64Decoder{
|
||||||
@ -111,7 +111,7 @@ pub const Base64Decoder = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// If the encoded buffer is detected to be invalid, returns error.InvalidPadding.
|
/// If the encoded buffer is detected to be invalid, returns error.InvalidPadding.
|
||||||
pub fn calcSize(decoder: &const Base64Decoder, source: []const u8) -> %usize {
|
pub fn calcSize(decoder: &const Base64Decoder, source: []const u8) %usize {
|
||||||
if (source.len % 4 != 0) return error.InvalidPadding;
|
if (source.len % 4 != 0) return error.InvalidPadding;
|
||||||
return calcDecodedSizeExactUnsafe(source, decoder.pad_char);
|
return calcDecodedSizeExactUnsafe(source, decoder.pad_char);
|
||||||
}
|
}
|
||||||
@ -119,7 +119,7 @@ pub const Base64Decoder = struct {
|
|||||||
/// dest.len must be what you get from ::calcSize.
|
/// dest.len must be what you get from ::calcSize.
|
||||||
/// invalid characters result in error.InvalidCharacter.
|
/// invalid characters result in error.InvalidCharacter.
|
||||||
/// invalid padding results in error.InvalidPadding.
|
/// invalid padding results in error.InvalidPadding.
|
||||||
pub fn decode(decoder: &const Base64Decoder, dest: []u8, source: []const u8) -> %void {
|
pub fn decode(decoder: &const Base64Decoder, dest: []u8, source: []const u8) %void {
|
||||||
assert(dest.len == (decoder.calcSize(source) catch unreachable));
|
assert(dest.len == (decoder.calcSize(source) catch unreachable));
|
||||||
assert(source.len % 4 == 0);
|
assert(source.len % 4 == 0);
|
||||||
|
|
||||||
@ -168,7 +168,7 @@ error OutputTooSmall;
|
|||||||
pub const Base64DecoderWithIgnore = struct {
|
pub const Base64DecoderWithIgnore = struct {
|
||||||
decoder: Base64Decoder,
|
decoder: Base64Decoder,
|
||||||
char_is_ignored: [256]bool,
|
char_is_ignored: [256]bool,
|
||||||
pub fn init(alphabet_chars: []const u8, pad_char: u8, ignore_chars: []const u8) -> Base64DecoderWithIgnore {
|
pub fn init(alphabet_chars: []const u8, pad_char: u8, ignore_chars: []const u8) Base64DecoderWithIgnore {
|
||||||
var result = Base64DecoderWithIgnore {
|
var result = Base64DecoderWithIgnore {
|
||||||
.decoder = Base64Decoder.init(alphabet_chars, pad_char),
|
.decoder = Base64Decoder.init(alphabet_chars, pad_char),
|
||||||
.char_is_ignored = []bool{false} ** 256,
|
.char_is_ignored = []bool{false} ** 256,
|
||||||
@ -185,7 +185,7 @@ pub const Base64DecoderWithIgnore = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// If no characters end up being ignored or padding, this will be the exact decoded size.
|
/// If no characters end up being ignored or padding, this will be the exact decoded size.
|
||||||
pub fn calcSizeUpperBound(encoded_len: usize) -> %usize {
|
pub fn calcSizeUpperBound(encoded_len: usize) %usize {
|
||||||
return @divTrunc(encoded_len, 4) * 3;
|
return @divTrunc(encoded_len, 4) * 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -193,7 +193,7 @@ pub const Base64DecoderWithIgnore = struct {
|
|||||||
/// Invalid padding results in error.InvalidPadding.
|
/// Invalid padding results in error.InvalidPadding.
|
||||||
/// Decoding more data than can fit in dest results in error.OutputTooSmall. See also ::calcSizeUpperBound.
|
/// Decoding more data than can fit in dest results in error.OutputTooSmall. See also ::calcSizeUpperBound.
|
||||||
/// Returns the number of bytes writen to dest.
|
/// Returns the number of bytes writen to dest.
|
||||||
pub fn decode(decoder_with_ignore: &const Base64DecoderWithIgnore, dest: []u8, source: []const u8) -> %usize {
|
pub fn decode(decoder_with_ignore: &const Base64DecoderWithIgnore, dest: []u8, source: []const u8) %usize {
|
||||||
const decoder = &decoder_with_ignore.decoder;
|
const decoder = &decoder_with_ignore.decoder;
|
||||||
|
|
||||||
var src_cursor: usize = 0;
|
var src_cursor: usize = 0;
|
||||||
@ -293,7 +293,7 @@ pub const Base64DecoderUnsafe = struct {
|
|||||||
char_to_index: [256]u8,
|
char_to_index: [256]u8,
|
||||||
pad_char: u8,
|
pad_char: u8,
|
||||||
|
|
||||||
pub fn init(alphabet_chars: []const u8, pad_char: u8) -> Base64DecoderUnsafe {
|
pub fn init(alphabet_chars: []const u8, pad_char: u8) Base64DecoderUnsafe {
|
||||||
assert(alphabet_chars.len == 64);
|
assert(alphabet_chars.len == 64);
|
||||||
var result = Base64DecoderUnsafe {
|
var result = Base64DecoderUnsafe {
|
||||||
.char_to_index = undefined,
|
.char_to_index = undefined,
|
||||||
@ -307,13 +307,13 @@ pub const Base64DecoderUnsafe = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The source buffer must be valid.
|
/// The source buffer must be valid.
|
||||||
pub fn calcSize(decoder: &const Base64DecoderUnsafe, source: []const u8) -> usize {
|
pub fn calcSize(decoder: &const Base64DecoderUnsafe, source: []const u8) usize {
|
||||||
return calcDecodedSizeExactUnsafe(source, decoder.pad_char);
|
return calcDecodedSizeExactUnsafe(source, decoder.pad_char);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// dest.len must be what you get from ::calcDecodedSizeExactUnsafe.
|
/// dest.len must be what you get from ::calcDecodedSizeExactUnsafe.
|
||||||
/// invalid characters or padding will result in undefined values.
|
/// invalid characters or padding will result in undefined values.
|
||||||
pub fn decode(decoder: &const Base64DecoderUnsafe, dest: []u8, source: []const u8) {
|
pub fn decode(decoder: &const Base64DecoderUnsafe, dest: []u8, source: []const u8) void {
|
||||||
assert(dest.len == decoder.calcSize(source));
|
assert(dest.len == decoder.calcSize(source));
|
||||||
|
|
||||||
var src_index: usize = 0;
|
var src_index: usize = 0;
|
||||||
@ -359,7 +359,7 @@ pub const Base64DecoderUnsafe = struct {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
fn calcDecodedSizeExactUnsafe(source: []const u8, pad_char: u8) -> usize {
|
fn calcDecodedSizeExactUnsafe(source: []const u8, pad_char: u8) usize {
|
||||||
if (source.len == 0) return 0;
|
if (source.len == 0) return 0;
|
||||||
var result = @divExact(source.len, 4) * 3;
|
var result = @divExact(source.len, 4) * 3;
|
||||||
if (source[source.len - 1] == pad_char) {
|
if (source[source.len - 1] == pad_char) {
|
||||||
@ -378,7 +378,7 @@ test "base64" {
|
|||||||
comptime (testBase64() catch unreachable);
|
comptime (testBase64() catch unreachable);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn testBase64() -> %void {
|
fn testBase64() %void {
|
||||||
try testAllApis("", "");
|
try testAllApis("", "");
|
||||||
try testAllApis("f", "Zg==");
|
try testAllApis("f", "Zg==");
|
||||||
try testAllApis("fo", "Zm8=");
|
try testAllApis("fo", "Zm8=");
|
||||||
@ -412,7 +412,7 @@ fn testBase64() -> %void {
|
|||||||
try testOutputTooSmallError("AAAAAA==");
|
try testOutputTooSmallError("AAAAAA==");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn testAllApis(expected_decoded: []const u8, expected_encoded: []const u8) -> %void {
|
fn testAllApis(expected_decoded: []const u8, expected_encoded: []const u8) %void {
|
||||||
// Base64Encoder
|
// Base64Encoder
|
||||||
{
|
{
|
||||||
var buffer: [0x100]u8 = undefined;
|
var buffer: [0x100]u8 = undefined;
|
||||||
@ -449,7 +449,7 @@ fn testAllApis(expected_decoded: []const u8, expected_encoded: []const u8) -> %v
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn testDecodeIgnoreSpace(expected_decoded: []const u8, encoded: []const u8) -> %void {
|
fn testDecodeIgnoreSpace(expected_decoded: []const u8, encoded: []const u8) %void {
|
||||||
const standard_decoder_ignore_space = Base64DecoderWithIgnore.init(
|
const standard_decoder_ignore_space = Base64DecoderWithIgnore.init(
|
||||||
standard_alphabet_chars, standard_pad_char, " ");
|
standard_alphabet_chars, standard_pad_char, " ");
|
||||||
var buffer: [0x100]u8 = undefined;
|
var buffer: [0x100]u8 = undefined;
|
||||||
@ -459,7 +459,7 @@ fn testDecodeIgnoreSpace(expected_decoded: []const u8, encoded: []const u8) -> %
|
|||||||
}
|
}
|
||||||
|
|
||||||
error ExpectedError;
|
error ExpectedError;
|
||||||
fn testError(encoded: []const u8, expected_err: error) -> %void {
|
fn testError(encoded: []const u8, expected_err: error) %void {
|
||||||
const standard_decoder_ignore_space = Base64DecoderWithIgnore.init(
|
const standard_decoder_ignore_space = Base64DecoderWithIgnore.init(
|
||||||
standard_alphabet_chars, standard_pad_char, " ");
|
standard_alphabet_chars, standard_pad_char, " ");
|
||||||
var buffer: [0x100]u8 = undefined;
|
var buffer: [0x100]u8 = undefined;
|
||||||
@ -475,7 +475,7 @@ fn testError(encoded: []const u8, expected_err: error) -> %void {
|
|||||||
} else |err| if (err != expected_err) return err;
|
} else |err| if (err != expected_err) return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn testOutputTooSmallError(encoded: []const u8) -> %void {
|
fn testOutputTooSmallError(encoded: []const u8) %void {
|
||||||
const standard_decoder_ignore_space = Base64DecoderWithIgnore.init(
|
const standard_decoder_ignore_space = Base64DecoderWithIgnore.init(
|
||||||
standard_alphabet_chars, standard_pad_char, " ");
|
standard_alphabet_chars, standard_pad_char, " ");
|
||||||
var buffer: [0x100]u8 = undefined;
|
var buffer: [0x100]u8 = undefined;
|
||||||
|
@ -9,14 +9,14 @@ pub const BufMap = struct {
|
|||||||
|
|
||||||
const BufMapHashMap = HashMap([]const u8, []const u8, mem.hash_slice_u8, mem.eql_slice_u8);
|
const BufMapHashMap = HashMap([]const u8, []const u8, mem.hash_slice_u8, mem.eql_slice_u8);
|
||||||
|
|
||||||
pub fn init(allocator: &Allocator) -> BufMap {
|
pub fn init(allocator: &Allocator) BufMap {
|
||||||
var self = BufMap {
|
var self = BufMap {
|
||||||
.hash_map = BufMapHashMap.init(allocator),
|
.hash_map = BufMapHashMap.init(allocator),
|
||||||
};
|
};
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: &BufMap) {
|
pub fn deinit(self: &BufMap) void {
|
||||||
var it = self.hash_map.iterator();
|
var it = self.hash_map.iterator();
|
||||||
while (true) {
|
while (true) {
|
||||||
const entry = it.next() ?? break;
|
const entry = it.next() ?? break;
|
||||||
@ -27,7 +27,7 @@ pub const BufMap = struct {
|
|||||||
self.hash_map.deinit();
|
self.hash_map.deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set(self: &BufMap, key: []const u8, value: []const u8) -> %void {
|
pub fn set(self: &BufMap, key: []const u8, value: []const u8) %void {
|
||||||
if (self.hash_map.get(key)) |entry| {
|
if (self.hash_map.get(key)) |entry| {
|
||||||
const value_copy = try self.copy(value);
|
const value_copy = try self.copy(value);
|
||||||
errdefer self.free(value_copy);
|
errdefer self.free(value_copy);
|
||||||
@ -42,32 +42,32 @@ pub const BufMap = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get(self: &BufMap, key: []const u8) -> ?[]const u8 {
|
pub fn get(self: &BufMap, key: []const u8) ?[]const u8 {
|
||||||
const entry = self.hash_map.get(key) ?? return null;
|
const entry = self.hash_map.get(key) ?? return null;
|
||||||
return entry.value;
|
return entry.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn delete(self: &BufMap, key: []const u8) {
|
pub fn delete(self: &BufMap, key: []const u8) void {
|
||||||
const entry = self.hash_map.remove(key) ?? return;
|
const entry = self.hash_map.remove(key) ?? return;
|
||||||
self.free(entry.key);
|
self.free(entry.key);
|
||||||
self.free(entry.value);
|
self.free(entry.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn count(self: &const BufMap) -> usize {
|
pub fn count(self: &const BufMap) usize {
|
||||||
return self.hash_map.size;
|
return self.hash_map.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iterator(self: &const BufMap) -> BufMapHashMap.Iterator {
|
pub fn iterator(self: &const BufMap) BufMapHashMap.Iterator {
|
||||||
return self.hash_map.iterator();
|
return self.hash_map.iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn free(self: &BufMap, value: []const u8) {
|
fn free(self: &BufMap, value: []const u8) void {
|
||||||
// remove the const
|
// remove the const
|
||||||
const mut_value = @ptrCast(&u8, value.ptr)[0..value.len];
|
const mut_value = @ptrCast(&u8, value.ptr)[0..value.len];
|
||||||
self.hash_map.allocator.free(mut_value);
|
self.hash_map.allocator.free(mut_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn copy(self: &BufMap, value: []const u8) -> %[]const u8 {
|
fn copy(self: &BufMap, value: []const u8) %[]const u8 {
|
||||||
const result = try self.hash_map.allocator.alloc(u8, value.len);
|
const result = try self.hash_map.allocator.alloc(u8, value.len);
|
||||||
mem.copy(u8, result, value);
|
mem.copy(u8, result, value);
|
||||||
return result;
|
return result;
|
||||||
|
@ -7,14 +7,14 @@ pub const BufSet = struct {
|
|||||||
|
|
||||||
const BufSetHashMap = HashMap([]const u8, void, mem.hash_slice_u8, mem.eql_slice_u8);
|
const BufSetHashMap = HashMap([]const u8, void, mem.hash_slice_u8, mem.eql_slice_u8);
|
||||||
|
|
||||||
pub fn init(a: &Allocator) -> BufSet {
|
pub fn init(a: &Allocator) BufSet {
|
||||||
var self = BufSet {
|
var self = BufSet {
|
||||||
.hash_map = BufSetHashMap.init(a),
|
.hash_map = BufSetHashMap.init(a),
|
||||||
};
|
};
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: &BufSet) {
|
pub fn deinit(self: &BufSet) void {
|
||||||
var it = self.hash_map.iterator();
|
var it = self.hash_map.iterator();
|
||||||
while (true) {
|
while (true) {
|
||||||
const entry = it.next() ?? break;
|
const entry = it.next() ?? break;
|
||||||
@ -24,7 +24,7 @@ pub const BufSet = struct {
|
|||||||
self.hash_map.deinit();
|
self.hash_map.deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn put(self: &BufSet, key: []const u8) -> %void {
|
pub fn put(self: &BufSet, key: []const u8) %void {
|
||||||
if (self.hash_map.get(key) == null) {
|
if (self.hash_map.get(key) == null) {
|
||||||
const key_copy = try self.copy(key);
|
const key_copy = try self.copy(key);
|
||||||
errdefer self.free(key_copy);
|
errdefer self.free(key_copy);
|
||||||
@ -32,30 +32,30 @@ pub const BufSet = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn delete(self: &BufSet, key: []const u8) {
|
pub fn delete(self: &BufSet, key: []const u8) void {
|
||||||
const entry = self.hash_map.remove(key) ?? return;
|
const entry = self.hash_map.remove(key) ?? return;
|
||||||
self.free(entry.key);
|
self.free(entry.key);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn count(self: &const BufSet) -> usize {
|
pub fn count(self: &const BufSet) usize {
|
||||||
return self.hash_map.size;
|
return self.hash_map.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iterator(self: &const BufSet) -> BufSetHashMap.Iterator {
|
pub fn iterator(self: &const BufSet) BufSetHashMap.Iterator {
|
||||||
return self.hash_map.iterator();
|
return self.hash_map.iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn allocator(self: &const BufSet) -> &Allocator {
|
pub fn allocator(self: &const BufSet) &Allocator {
|
||||||
return self.hash_map.allocator;
|
return self.hash_map.allocator;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn free(self: &BufSet, value: []const u8) {
|
fn free(self: &BufSet, value: []const u8) void {
|
||||||
// remove the const
|
// remove the const
|
||||||
const mut_value = @ptrCast(&u8, value.ptr)[0..value.len];
|
const mut_value = @ptrCast(&u8, value.ptr)[0..value.len];
|
||||||
self.hash_map.allocator.free(mut_value);
|
self.hash_map.allocator.free(mut_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn copy(self: &BufSet, value: []const u8) -> %[]const u8 {
|
fn copy(self: &BufSet, value: []const u8) %[]const u8 {
|
||||||
const result = try self.hash_map.allocator.alloc(u8, value.len);
|
const result = try self.hash_map.allocator.alloc(u8, value.len);
|
||||||
mem.copy(u8, result, value);
|
mem.copy(u8, result, value);
|
||||||
return result;
|
return result;
|
||||||
|
@ -12,14 +12,14 @@ pub const Buffer = struct {
|
|||||||
list: ArrayList(u8),
|
list: ArrayList(u8),
|
||||||
|
|
||||||
/// Must deinitialize with deinit.
|
/// Must deinitialize with deinit.
|
||||||
pub fn init(allocator: &Allocator, m: []const u8) -> %Buffer {
|
pub fn init(allocator: &Allocator, m: []const u8) %Buffer {
|
||||||
var self = try initSize(allocator, m.len);
|
var self = try initSize(allocator, m.len);
|
||||||
mem.copy(u8, self.list.items, m);
|
mem.copy(u8, self.list.items, m);
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Must deinitialize with deinit.
|
/// Must deinitialize with deinit.
|
||||||
pub fn initSize(allocator: &Allocator, size: usize) -> %Buffer {
|
pub fn initSize(allocator: &Allocator, size: usize) %Buffer {
|
||||||
var self = initNull(allocator);
|
var self = initNull(allocator);
|
||||||
try self.resize(size);
|
try self.resize(size);
|
||||||
return self;
|
return self;
|
||||||
@ -30,21 +30,21 @@ pub const Buffer = struct {
|
|||||||
/// * ::replaceContents
|
/// * ::replaceContents
|
||||||
/// * ::replaceContentsBuffer
|
/// * ::replaceContentsBuffer
|
||||||
/// * ::resize
|
/// * ::resize
|
||||||
pub fn initNull(allocator: &Allocator) -> Buffer {
|
pub fn initNull(allocator: &Allocator) Buffer {
|
||||||
return Buffer {
|
return Buffer {
|
||||||
.list = ArrayList(u8).init(allocator),
|
.list = ArrayList(u8).init(allocator),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Must deinitialize with deinit.
|
/// Must deinitialize with deinit.
|
||||||
pub fn initFromBuffer(buffer: &const Buffer) -> %Buffer {
|
pub fn initFromBuffer(buffer: &const Buffer) %Buffer {
|
||||||
return Buffer.init(buffer.list.allocator, buffer.toSliceConst());
|
return Buffer.init(buffer.list.allocator, buffer.toSliceConst());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Buffer takes ownership of the passed in slice. The slice must have been
|
/// Buffer takes ownership of the passed in slice. The slice must have been
|
||||||
/// allocated with `allocator`.
|
/// allocated with `allocator`.
|
||||||
/// Must deinitialize with deinit.
|
/// Must deinitialize with deinit.
|
||||||
pub fn fromOwnedSlice(allocator: &Allocator, slice: []u8) -> Buffer {
|
pub fn fromOwnedSlice(allocator: &Allocator, slice: []u8) Buffer {
|
||||||
var self = Buffer {
|
var self = Buffer {
|
||||||
.list = ArrayList(u8).fromOwnedSlice(allocator, slice),
|
.list = ArrayList(u8).fromOwnedSlice(allocator, slice),
|
||||||
};
|
};
|
||||||
@ -54,7 +54,7 @@ pub const Buffer = struct {
|
|||||||
|
|
||||||
/// The caller owns the returned memory. The Buffer becomes null and
|
/// The caller owns the returned memory. The Buffer becomes null and
|
||||||
/// is safe to `deinit`.
|
/// is safe to `deinit`.
|
||||||
pub fn toOwnedSlice(self: &Buffer) -> []u8 {
|
pub fn toOwnedSlice(self: &Buffer) []u8 {
|
||||||
const allocator = self.list.allocator;
|
const allocator = self.list.allocator;
|
||||||
const result = allocator.shrink(u8, self.list.items, self.len());
|
const result = allocator.shrink(u8, self.list.items, self.len());
|
||||||
*self = initNull(allocator);
|
*self = initNull(allocator);
|
||||||
@ -62,55 +62,55 @@ pub const Buffer = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn deinit(self: &Buffer) {
|
pub fn deinit(self: &Buffer) void {
|
||||||
self.list.deinit();
|
self.list.deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn toSlice(self: &Buffer) -> []u8 {
|
pub fn toSlice(self: &Buffer) []u8 {
|
||||||
return self.list.toSlice()[0..self.len()];
|
return self.list.toSlice()[0..self.len()];
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn toSliceConst(self: &const Buffer) -> []const u8 {
|
pub fn toSliceConst(self: &const Buffer) []const u8 {
|
||||||
return self.list.toSliceConst()[0..self.len()];
|
return self.list.toSliceConst()[0..self.len()];
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn shrink(self: &Buffer, new_len: usize) {
|
pub fn shrink(self: &Buffer, new_len: usize) void {
|
||||||
assert(new_len <= self.len());
|
assert(new_len <= self.len());
|
||||||
self.list.shrink(new_len + 1);
|
self.list.shrink(new_len + 1);
|
||||||
self.list.items[self.len()] = 0;
|
self.list.items[self.len()] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resize(self: &Buffer, new_len: usize) -> %void {
|
pub fn resize(self: &Buffer, new_len: usize) %void {
|
||||||
try self.list.resize(new_len + 1);
|
try self.list.resize(new_len + 1);
|
||||||
self.list.items[self.len()] = 0;
|
self.list.items[self.len()] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn isNull(self: &const Buffer) -> bool {
|
pub fn isNull(self: &const Buffer) bool {
|
||||||
return self.list.len == 0;
|
return self.list.len == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn len(self: &const Buffer) -> usize {
|
pub fn len(self: &const Buffer) usize {
|
||||||
return self.list.len - 1;
|
return self.list.len - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn append(self: &Buffer, m: []const u8) -> %void {
|
pub fn append(self: &Buffer, m: []const u8) %void {
|
||||||
const old_len = self.len();
|
const old_len = self.len();
|
||||||
try self.resize(old_len + m.len);
|
try self.resize(old_len + m.len);
|
||||||
mem.copy(u8, self.list.toSlice()[old_len..], m);
|
mem.copy(u8, self.list.toSlice()[old_len..], m);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: remove, use OutStream for this
|
// TODO: remove, use OutStream for this
|
||||||
pub fn appendFormat(self: &Buffer, comptime format: []const u8, args: ...) -> %void {
|
pub fn appendFormat(self: &Buffer, comptime format: []const u8, args: ...) %void {
|
||||||
return fmt.format(self, append, format, args);
|
return fmt.format(self, append, format, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: remove, use OutStream for this
|
// TODO: remove, use OutStream for this
|
||||||
pub fn appendByte(self: &Buffer, byte: u8) -> %void {
|
pub fn appendByte(self: &Buffer, byte: u8) %void {
|
||||||
return self.appendByteNTimes(byte, 1);
|
return self.appendByteNTimes(byte, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: remove, use OutStream for this
|
// TODO: remove, use OutStream for this
|
||||||
pub fn appendByteNTimes(self: &Buffer, byte: u8, count: usize) -> %void {
|
pub fn appendByteNTimes(self: &Buffer, byte: u8, count: usize) %void {
|
||||||
var prev_size: usize = self.len();
|
var prev_size: usize = self.len();
|
||||||
const new_size = prev_size + count;
|
const new_size = prev_size + count;
|
||||||
try self.resize(new_size);
|
try self.resize(new_size);
|
||||||
@ -121,29 +121,29 @@ pub const Buffer = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn eql(self: &const Buffer, m: []const u8) -> bool {
|
pub fn eql(self: &const Buffer, m: []const u8) bool {
|
||||||
return mem.eql(u8, self.toSliceConst(), m);
|
return mem.eql(u8, self.toSliceConst(), m);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn startsWith(self: &const Buffer, m: []const u8) -> bool {
|
pub fn startsWith(self: &const Buffer, m: []const u8) bool {
|
||||||
if (self.len() < m.len) return false;
|
if (self.len() < m.len) return false;
|
||||||
return mem.eql(u8, self.list.items[0..m.len], m);
|
return mem.eql(u8, self.list.items[0..m.len], m);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn endsWith(self: &const Buffer, m: []const u8) -> bool {
|
pub fn endsWith(self: &const Buffer, m: []const u8) bool {
|
||||||
const l = self.len();
|
const l = self.len();
|
||||||
if (l < m.len) return false;
|
if (l < m.len) return false;
|
||||||
const start = l - m.len;
|
const start = l - m.len;
|
||||||
return mem.eql(u8, self.list.items[start..l], m);
|
return mem.eql(u8, self.list.items[start..l], m);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn replaceContents(self: &const Buffer, m: []const u8) -> %void {
|
pub fn replaceContents(self: &const Buffer, m: []const u8) %void {
|
||||||
try self.resize(m.len);
|
try self.resize(m.len);
|
||||||
mem.copy(u8, self.list.toSlice(), m);
|
mem.copy(u8, self.list.toSlice(), m);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// For passing to C functions.
|
/// For passing to C functions.
|
||||||
pub fn ptr(self: &const Buffer) -> &u8 {
|
pub fn ptr(self: &const Buffer) &u8 {
|
||||||
return self.list.items.ptr;
|
return self.list.items.ptr;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
248
std/build.zig
248
std/build.zig
@ -90,7 +90,7 @@ pub const Builder = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub fn init(allocator: &Allocator, zig_exe: []const u8, build_root: []const u8,
|
pub fn init(allocator: &Allocator, zig_exe: []const u8, build_root: []const u8,
|
||||||
cache_root: []const u8) -> Builder
|
cache_root: []const u8) Builder
|
||||||
{
|
{
|
||||||
var self = Builder {
|
var self = Builder {
|
||||||
.zig_exe = zig_exe,
|
.zig_exe = zig_exe,
|
||||||
@ -136,7 +136,7 @@ pub const Builder = struct {
|
|||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: &Builder) {
|
pub fn deinit(self: &Builder) void {
|
||||||
self.lib_paths.deinit();
|
self.lib_paths.deinit();
|
||||||
self.include_paths.deinit();
|
self.include_paths.deinit();
|
||||||
self.rpaths.deinit();
|
self.rpaths.deinit();
|
||||||
@ -144,85 +144,85 @@ pub const Builder = struct {
|
|||||||
self.top_level_steps.deinit();
|
self.top_level_steps.deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setInstallPrefix(self: &Builder, maybe_prefix: ?[]const u8) {
|
pub fn setInstallPrefix(self: &Builder, maybe_prefix: ?[]const u8) void {
|
||||||
self.prefix = maybe_prefix ?? "/usr/local"; // TODO better default
|
self.prefix = maybe_prefix ?? "/usr/local"; // TODO better default
|
||||||
self.lib_dir = os.path.join(self.allocator, self.prefix, "lib") catch unreachable;
|
self.lib_dir = os.path.join(self.allocator, self.prefix, "lib") catch unreachable;
|
||||||
self.exe_dir = os.path.join(self.allocator, self.prefix, "bin") catch unreachable;
|
self.exe_dir = os.path.join(self.allocator, self.prefix, "bin") catch unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addExecutable(self: &Builder, name: []const u8, root_src: ?[]const u8) -> &LibExeObjStep {
|
pub fn addExecutable(self: &Builder, name: []const u8, root_src: ?[]const u8) &LibExeObjStep {
|
||||||
return LibExeObjStep.createExecutable(self, name, root_src);
|
return LibExeObjStep.createExecutable(self, name, root_src);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addObject(self: &Builder, name: []const u8, root_src: []const u8) -> &LibExeObjStep {
|
pub fn addObject(self: &Builder, name: []const u8, root_src: []const u8) &LibExeObjStep {
|
||||||
return LibExeObjStep.createObject(self, name, root_src);
|
return LibExeObjStep.createObject(self, name, root_src);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addSharedLibrary(self: &Builder, name: []const u8, root_src: ?[]const u8,
|
pub fn addSharedLibrary(self: &Builder, name: []const u8, root_src: ?[]const u8,
|
||||||
ver: &const Version) -> &LibExeObjStep
|
ver: &const Version) &LibExeObjStep
|
||||||
{
|
{
|
||||||
return LibExeObjStep.createSharedLibrary(self, name, root_src, ver);
|
return LibExeObjStep.createSharedLibrary(self, name, root_src, ver);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addStaticLibrary(self: &Builder, name: []const u8, root_src: ?[]const u8) -> &LibExeObjStep {
|
pub fn addStaticLibrary(self: &Builder, name: []const u8, root_src: ?[]const u8) &LibExeObjStep {
|
||||||
return LibExeObjStep.createStaticLibrary(self, name, root_src);
|
return LibExeObjStep.createStaticLibrary(self, name, root_src);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addTest(self: &Builder, root_src: []const u8) -> &TestStep {
|
pub fn addTest(self: &Builder, root_src: []const u8) &TestStep {
|
||||||
const test_step = self.allocator.create(TestStep) catch unreachable;
|
const test_step = self.allocator.create(TestStep) catch unreachable;
|
||||||
*test_step = TestStep.init(self, root_src);
|
*test_step = TestStep.init(self, root_src);
|
||||||
return test_step;
|
return test_step;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addAssemble(self: &Builder, name: []const u8, src: []const u8) -> &LibExeObjStep {
|
pub fn addAssemble(self: &Builder, name: []const u8, src: []const u8) &LibExeObjStep {
|
||||||
const obj_step = LibExeObjStep.createObject(self, name, null);
|
const obj_step = LibExeObjStep.createObject(self, name, null);
|
||||||
obj_step.addAssemblyFile(src);
|
obj_step.addAssemblyFile(src);
|
||||||
return obj_step;
|
return obj_step;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addCStaticLibrary(self: &Builder, name: []const u8) -> &LibExeObjStep {
|
pub fn addCStaticLibrary(self: &Builder, name: []const u8) &LibExeObjStep {
|
||||||
return LibExeObjStep.createCStaticLibrary(self, name);
|
return LibExeObjStep.createCStaticLibrary(self, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addCSharedLibrary(self: &Builder, name: []const u8, ver: &const Version) -> &LibExeObjStep {
|
pub fn addCSharedLibrary(self: &Builder, name: []const u8, ver: &const Version) &LibExeObjStep {
|
||||||
return LibExeObjStep.createCSharedLibrary(self, name, ver);
|
return LibExeObjStep.createCSharedLibrary(self, name, ver);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addCExecutable(self: &Builder, name: []const u8) -> &LibExeObjStep {
|
pub fn addCExecutable(self: &Builder, name: []const u8) &LibExeObjStep {
|
||||||
return LibExeObjStep.createCExecutable(self, name);
|
return LibExeObjStep.createCExecutable(self, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addCObject(self: &Builder, name: []const u8, src: []const u8) -> &LibExeObjStep {
|
pub fn addCObject(self: &Builder, name: []const u8, src: []const u8) &LibExeObjStep {
|
||||||
return LibExeObjStep.createCObject(self, name, src);
|
return LibExeObjStep.createCObject(self, name, src);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ::argv is copied.
|
/// ::argv is copied.
|
||||||
pub fn addCommand(self: &Builder, cwd: ?[]const u8, env_map: &const BufMap,
|
pub fn addCommand(self: &Builder, cwd: ?[]const u8, env_map: &const BufMap,
|
||||||
argv: []const []const u8) -> &CommandStep
|
argv: []const []const u8) &CommandStep
|
||||||
{
|
{
|
||||||
return CommandStep.create(self, cwd, env_map, argv);
|
return CommandStep.create(self, cwd, env_map, argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addWriteFile(self: &Builder, file_path: []const u8, data: []const u8) -> &WriteFileStep {
|
pub fn addWriteFile(self: &Builder, file_path: []const u8, data: []const u8) &WriteFileStep {
|
||||||
const write_file_step = self.allocator.create(WriteFileStep) catch unreachable;
|
const write_file_step = self.allocator.create(WriteFileStep) catch unreachable;
|
||||||
*write_file_step = WriteFileStep.init(self, file_path, data);
|
*write_file_step = WriteFileStep.init(self, file_path, data);
|
||||||
return write_file_step;
|
return write_file_step;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addLog(self: &Builder, comptime format: []const u8, args: ...) -> &LogStep {
|
pub fn addLog(self: &Builder, comptime format: []const u8, args: ...) &LogStep {
|
||||||
const data = self.fmt(format, args);
|
const data = self.fmt(format, args);
|
||||||
const log_step = self.allocator.create(LogStep) catch unreachable;
|
const log_step = self.allocator.create(LogStep) catch unreachable;
|
||||||
*log_step = LogStep.init(self, data);
|
*log_step = LogStep.init(self, data);
|
||||||
return log_step;
|
return log_step;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addRemoveDirTree(self: &Builder, dir_path: []const u8) -> &RemoveDirStep {
|
pub fn addRemoveDirTree(self: &Builder, dir_path: []const u8) &RemoveDirStep {
|
||||||
const remove_dir_step = self.allocator.create(RemoveDirStep) catch unreachable;
|
const remove_dir_step = self.allocator.create(RemoveDirStep) catch unreachable;
|
||||||
*remove_dir_step = RemoveDirStep.init(self, dir_path);
|
*remove_dir_step = RemoveDirStep.init(self, dir_path);
|
||||||
return remove_dir_step;
|
return remove_dir_step;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn version(self: &const Builder, major: u32, minor: u32, patch: u32) -> Version {
|
pub fn version(self: &const Builder, major: u32, minor: u32, patch: u32) Version {
|
||||||
return Version {
|
return Version {
|
||||||
.major = major,
|
.major = major,
|
||||||
.minor = minor,
|
.minor = minor,
|
||||||
@ -230,19 +230,19 @@ pub const Builder = struct {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addCIncludePath(self: &Builder, path: []const u8) {
|
pub fn addCIncludePath(self: &Builder, path: []const u8) void {
|
||||||
self.include_paths.append(path) catch unreachable;
|
self.include_paths.append(path) catch unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addRPath(self: &Builder, path: []const u8) {
|
pub fn addRPath(self: &Builder, path: []const u8) void {
|
||||||
self.rpaths.append(path) catch unreachable;
|
self.rpaths.append(path) catch unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addLibPath(self: &Builder, path: []const u8) {
|
pub fn addLibPath(self: &Builder, path: []const u8) void {
|
||||||
self.lib_paths.append(path) catch unreachable;
|
self.lib_paths.append(path) catch unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn make(self: &Builder, step_names: []const []const u8) -> %void {
|
pub fn make(self: &Builder, step_names: []const []const u8) %void {
|
||||||
var wanted_steps = ArrayList(&Step).init(self.allocator);
|
var wanted_steps = ArrayList(&Step).init(self.allocator);
|
||||||
defer wanted_steps.deinit();
|
defer wanted_steps.deinit();
|
||||||
|
|
||||||
@ -260,7 +260,7 @@ pub const Builder = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getInstallStep(self: &Builder) -> &Step {
|
pub fn getInstallStep(self: &Builder) &Step {
|
||||||
if (self.have_install_step)
|
if (self.have_install_step)
|
||||||
return &self.install_tls.step;
|
return &self.install_tls.step;
|
||||||
|
|
||||||
@ -269,7 +269,7 @@ pub const Builder = struct {
|
|||||||
return &self.install_tls.step;
|
return &self.install_tls.step;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getUninstallStep(self: &Builder) -> &Step {
|
pub fn getUninstallStep(self: &Builder) &Step {
|
||||||
if (self.have_uninstall_step)
|
if (self.have_uninstall_step)
|
||||||
return &self.uninstall_tls.step;
|
return &self.uninstall_tls.step;
|
||||||
|
|
||||||
@ -278,7 +278,7 @@ pub const Builder = struct {
|
|||||||
return &self.uninstall_tls.step;
|
return &self.uninstall_tls.step;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn makeUninstall(uninstall_step: &Step) -> %void {
|
fn makeUninstall(uninstall_step: &Step) %void {
|
||||||
const uninstall_tls = @fieldParentPtr(TopLevelStep, "step", uninstall_step);
|
const uninstall_tls = @fieldParentPtr(TopLevelStep, "step", uninstall_step);
|
||||||
const self = @fieldParentPtr(Builder, "uninstall_tls", uninstall_tls);
|
const self = @fieldParentPtr(Builder, "uninstall_tls", uninstall_tls);
|
||||||
|
|
||||||
@ -292,7 +292,7 @@ pub const Builder = struct {
|
|||||||
// TODO remove empty directories
|
// TODO remove empty directories
|
||||||
}
|
}
|
||||||
|
|
||||||
fn makeOneStep(self: &Builder, s: &Step) -> %void {
|
fn makeOneStep(self: &Builder, s: &Step) %void {
|
||||||
if (s.loop_flag) {
|
if (s.loop_flag) {
|
||||||
warn("Dependency loop detected:\n {}\n", s.name);
|
warn("Dependency loop detected:\n {}\n", s.name);
|
||||||
return error.DependencyLoopDetected;
|
return error.DependencyLoopDetected;
|
||||||
@ -313,7 +313,7 @@ pub const Builder = struct {
|
|||||||
try s.make();
|
try s.make();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getTopLevelStepByName(self: &Builder, name: []const u8) -> %&Step {
|
fn getTopLevelStepByName(self: &Builder, name: []const u8) %&Step {
|
||||||
for (self.top_level_steps.toSliceConst()) |top_level_step| {
|
for (self.top_level_steps.toSliceConst()) |top_level_step| {
|
||||||
if (mem.eql(u8, top_level_step.step.name, name)) {
|
if (mem.eql(u8, top_level_step.step.name, name)) {
|
||||||
return &top_level_step.step;
|
return &top_level_step.step;
|
||||||
@ -323,7 +323,7 @@ pub const Builder = struct {
|
|||||||
return error.InvalidStepName;
|
return error.InvalidStepName;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn processNixOSEnvVars(self: &Builder) {
|
fn processNixOSEnvVars(self: &Builder) void {
|
||||||
if (os.getEnvVarOwned(self.allocator, "NIX_CFLAGS_COMPILE")) |nix_cflags_compile| {
|
if (os.getEnvVarOwned(self.allocator, "NIX_CFLAGS_COMPILE")) |nix_cflags_compile| {
|
||||||
var it = mem.split(nix_cflags_compile, " ");
|
var it = mem.split(nix_cflags_compile, " ");
|
||||||
while (true) {
|
while (true) {
|
||||||
@ -365,7 +365,7 @@ pub const Builder = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn option(self: &Builder, comptime T: type, name: []const u8, description: []const u8) -> ?T {
|
pub fn option(self: &Builder, comptime T: type, name: []const u8, description: []const u8) ?T {
|
||||||
const type_id = comptime typeToEnum(T);
|
const type_id = comptime typeToEnum(T);
|
||||||
const available_option = AvailableOption {
|
const available_option = AvailableOption {
|
||||||
.name = name,
|
.name = name,
|
||||||
@ -418,7 +418,7 @@ pub const Builder = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn step(self: &Builder, name: []const u8, description: []const u8) -> &Step {
|
pub fn step(self: &Builder, name: []const u8, description: []const u8) &Step {
|
||||||
const step_info = self.allocator.create(TopLevelStep) catch unreachable;
|
const step_info = self.allocator.create(TopLevelStep) catch unreachable;
|
||||||
*step_info = TopLevelStep {
|
*step_info = TopLevelStep {
|
||||||
.step = Step.initNoOp(name, self.allocator),
|
.step = Step.initNoOp(name, self.allocator),
|
||||||
@ -428,7 +428,7 @@ pub const Builder = struct {
|
|||||||
return &step_info.step;
|
return &step_info.step;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn standardReleaseOptions(self: &Builder) -> builtin.Mode {
|
pub fn standardReleaseOptions(self: &Builder) builtin.Mode {
|
||||||
if (self.release_mode) |mode| return mode;
|
if (self.release_mode) |mode| return mode;
|
||||||
|
|
||||||
const release_safe = self.option(bool, "release-safe", "optimizations on and safety on") ?? false;
|
const release_safe = self.option(bool, "release-safe", "optimizations on and safety on") ?? false;
|
||||||
@ -449,7 +449,7 @@ pub const Builder = struct {
|
|||||||
return mode;
|
return mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addUserInputOption(self: &Builder, name: []const u8, value: []const u8) -> bool {
|
pub fn addUserInputOption(self: &Builder, name: []const u8, value: []const u8) bool {
|
||||||
if (self.user_input_options.put(name, UserInputOption {
|
if (self.user_input_options.put(name, UserInputOption {
|
||||||
.name = name,
|
.name = name,
|
||||||
.value = UserValue { .Scalar = value },
|
.value = UserValue { .Scalar = value },
|
||||||
@ -486,7 +486,7 @@ pub const Builder = struct {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addUserInputFlag(self: &Builder, name: []const u8) -> bool {
|
pub fn addUserInputFlag(self: &Builder, name: []const u8) bool {
|
||||||
if (self.user_input_options.put(name, UserInputOption {
|
if (self.user_input_options.put(name, UserInputOption {
|
||||||
.name = name,
|
.name = name,
|
||||||
.value = UserValue {.Flag = {} },
|
.value = UserValue {.Flag = {} },
|
||||||
@ -507,7 +507,7 @@ pub const Builder = struct {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn typeToEnum(comptime T: type) -> TypeId {
|
fn typeToEnum(comptime T: type) TypeId {
|
||||||
return switch (@typeId(T)) {
|
return switch (@typeId(T)) {
|
||||||
builtin.TypeId.Int => TypeId.Int,
|
builtin.TypeId.Int => TypeId.Int,
|
||||||
builtin.TypeId.Float => TypeId.Float,
|
builtin.TypeId.Float => TypeId.Float,
|
||||||
@ -520,11 +520,11 @@ pub const Builder = struct {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn markInvalidUserInput(self: &Builder) {
|
fn markInvalidUserInput(self: &Builder) void {
|
||||||
self.invalid_user_input = true;
|
self.invalid_user_input = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn typeIdName(id: TypeId) -> []const u8 {
|
pub fn typeIdName(id: TypeId) []const u8 {
|
||||||
return switch (id) {
|
return switch (id) {
|
||||||
TypeId.Bool => "bool",
|
TypeId.Bool => "bool",
|
||||||
TypeId.Int => "int",
|
TypeId.Int => "int",
|
||||||
@ -534,7 +534,7 @@ pub const Builder = struct {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn validateUserInputDidItFail(self: &Builder) -> bool {
|
pub fn validateUserInputDidItFail(self: &Builder) bool {
|
||||||
// make sure all args are used
|
// make sure all args are used
|
||||||
var it = self.user_input_options.iterator();
|
var it = self.user_input_options.iterator();
|
||||||
while (true) {
|
while (true) {
|
||||||
@ -548,11 +548,11 @@ pub const Builder = struct {
|
|||||||
return self.invalid_user_input;
|
return self.invalid_user_input;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn spawnChild(self: &Builder, argv: []const []const u8) -> %void {
|
fn spawnChild(self: &Builder, argv: []const []const u8) %void {
|
||||||
return self.spawnChildEnvMap(null, &self.env_map, argv);
|
return self.spawnChildEnvMap(null, &self.env_map, argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn printCmd(cwd: ?[]const u8, argv: []const []const u8) {
|
fn printCmd(cwd: ?[]const u8, argv: []const []const u8) void {
|
||||||
if (cwd) |yes_cwd| warn("cd {} && ", yes_cwd);
|
if (cwd) |yes_cwd| warn("cd {} && ", yes_cwd);
|
||||||
for (argv) |arg| {
|
for (argv) |arg| {
|
||||||
warn("{} ", arg);
|
warn("{} ", arg);
|
||||||
@ -561,7 +561,7 @@ pub const Builder = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn spawnChildEnvMap(self: &Builder, cwd: ?[]const u8, env_map: &const BufMap,
|
fn spawnChildEnvMap(self: &Builder, cwd: ?[]const u8, env_map: &const BufMap,
|
||||||
argv: []const []const u8) -> %void
|
argv: []const []const u8) %void
|
||||||
{
|
{
|
||||||
if (self.verbose) {
|
if (self.verbose) {
|
||||||
printCmd(cwd, argv);
|
printCmd(cwd, argv);
|
||||||
@ -595,28 +595,28 @@ pub const Builder = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn makePath(self: &Builder, path: []const u8) -> %void {
|
pub fn makePath(self: &Builder, path: []const u8) %void {
|
||||||
os.makePath(self.allocator, self.pathFromRoot(path)) catch |err| {
|
os.makePath(self.allocator, self.pathFromRoot(path)) catch |err| {
|
||||||
warn("Unable to create path {}: {}\n", path, @errorName(err));
|
warn("Unable to create path {}: {}\n", path, @errorName(err));
|
||||||
return err;
|
return err;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn installArtifact(self: &Builder, artifact: &LibExeObjStep) {
|
pub fn installArtifact(self: &Builder, artifact: &LibExeObjStep) void {
|
||||||
self.getInstallStep().dependOn(&self.addInstallArtifact(artifact).step);
|
self.getInstallStep().dependOn(&self.addInstallArtifact(artifact).step);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addInstallArtifact(self: &Builder, artifact: &LibExeObjStep) -> &InstallArtifactStep {
|
pub fn addInstallArtifact(self: &Builder, artifact: &LibExeObjStep) &InstallArtifactStep {
|
||||||
return InstallArtifactStep.create(self, artifact);
|
return InstallArtifactStep.create(self, artifact);
|
||||||
}
|
}
|
||||||
|
|
||||||
///::dest_rel_path is relative to prefix path or it can be an absolute path
|
///::dest_rel_path is relative to prefix path or it can be an absolute path
|
||||||
pub fn installFile(self: &Builder, src_path: []const u8, dest_rel_path: []const u8) {
|
pub fn installFile(self: &Builder, src_path: []const u8, dest_rel_path: []const u8) void {
|
||||||
self.getInstallStep().dependOn(&self.addInstallFile(src_path, dest_rel_path).step);
|
self.getInstallStep().dependOn(&self.addInstallFile(src_path, dest_rel_path).step);
|
||||||
}
|
}
|
||||||
|
|
||||||
///::dest_rel_path is relative to prefix path or it can be an absolute path
|
///::dest_rel_path is relative to prefix path or it can be an absolute path
|
||||||
pub fn addInstallFile(self: &Builder, src_path: []const u8, dest_rel_path: []const u8) -> &InstallFileStep {
|
pub fn addInstallFile(self: &Builder, src_path: []const u8, dest_rel_path: []const u8) &InstallFileStep {
|
||||||
const full_dest_path = os.path.resolve(self.allocator, self.prefix, dest_rel_path) catch unreachable;
|
const full_dest_path = os.path.resolve(self.allocator, self.prefix, dest_rel_path) catch unreachable;
|
||||||
self.pushInstalledFile(full_dest_path);
|
self.pushInstalledFile(full_dest_path);
|
||||||
|
|
||||||
@ -625,16 +625,16 @@ pub const Builder = struct {
|
|||||||
return install_step;
|
return install_step;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pushInstalledFile(self: &Builder, full_path: []const u8) {
|
pub fn pushInstalledFile(self: &Builder, full_path: []const u8) void {
|
||||||
_ = self.getUninstallStep();
|
_ = self.getUninstallStep();
|
||||||
self.installed_files.append(full_path) catch unreachable;
|
self.installed_files.append(full_path) catch unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn copyFile(self: &Builder, source_path: []const u8, dest_path: []const u8) -> %void {
|
fn copyFile(self: &Builder, source_path: []const u8, dest_path: []const u8) %void {
|
||||||
return self.copyFileMode(source_path, dest_path, 0o666);
|
return self.copyFileMode(source_path, dest_path, 0o666);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn copyFileMode(self: &Builder, source_path: []const u8, dest_path: []const u8, mode: usize) -> %void {
|
fn copyFileMode(self: &Builder, source_path: []const u8, dest_path: []const u8, mode: usize) %void {
|
||||||
if (self.verbose) {
|
if (self.verbose) {
|
||||||
warn("cp {} {}\n", source_path, dest_path);
|
warn("cp {} {}\n", source_path, dest_path);
|
||||||
}
|
}
|
||||||
@ -651,15 +651,15 @@ pub const Builder = struct {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pathFromRoot(self: &Builder, rel_path: []const u8) -> []u8 {
|
fn pathFromRoot(self: &Builder, rel_path: []const u8) []u8 {
|
||||||
return os.path.resolve(self.allocator, self.build_root, rel_path) catch unreachable;
|
return os.path.resolve(self.allocator, self.build_root, rel_path) catch unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fmt(self: &Builder, comptime format: []const u8, args: ...) -> []u8 {
|
pub fn fmt(self: &Builder, comptime format: []const u8, args: ...) []u8 {
|
||||||
return fmt_lib.allocPrint(self.allocator, format, args) catch unreachable;
|
return fmt_lib.allocPrint(self.allocator, format, args) catch unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getCCExe(self: &Builder) -> []const u8 {
|
fn getCCExe(self: &Builder) []const u8 {
|
||||||
if (builtin.environ == builtin.Environ.msvc) {
|
if (builtin.environ == builtin.Environ.msvc) {
|
||||||
return "cl.exe";
|
return "cl.exe";
|
||||||
} else {
|
} else {
|
||||||
@ -672,7 +672,7 @@ pub const Builder = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn findProgram(self: &Builder, names: []const []const u8, paths: []const []const u8) -> %[]const u8 {
|
pub fn findProgram(self: &Builder, names: []const []const u8, paths: []const []const u8) %[]const u8 {
|
||||||
// TODO report error for ambiguous situations
|
// TODO report error for ambiguous situations
|
||||||
const exe_extension = (Target { .Native = {}}).exeFileExt();
|
const exe_extension = (Target { .Native = {}}).exeFileExt();
|
||||||
for (self.search_prefixes.toSliceConst()) |search_prefix| {
|
for (self.search_prefixes.toSliceConst()) |search_prefix| {
|
||||||
@ -721,7 +721,7 @@ pub const Builder = struct {
|
|||||||
return error.FileNotFound;
|
return error.FileNotFound;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn exec(self: &Builder, argv: []const []const u8) -> %[]u8 {
|
pub fn exec(self: &Builder, argv: []const []const u8) %[]u8 {
|
||||||
const max_output_size = 100 * 1024;
|
const max_output_size = 100 * 1024;
|
||||||
const result = try os.ChildProcess.exec(self.allocator, argv, null, null, max_output_size);
|
const result = try os.ChildProcess.exec(self.allocator, argv, null, null, max_output_size);
|
||||||
switch (result.term) {
|
switch (result.term) {
|
||||||
@ -743,7 +743,7 @@ pub const Builder = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addSearchPrefix(self: &Builder, search_prefix: []const u8) {
|
pub fn addSearchPrefix(self: &Builder, search_prefix: []const u8) void {
|
||||||
self.search_prefixes.append(search_prefix) catch unreachable;
|
self.search_prefixes.append(search_prefix) catch unreachable;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -764,7 +764,7 @@ pub const Target = union(enum) {
|
|||||||
Native: void,
|
Native: void,
|
||||||
Cross: CrossTarget,
|
Cross: CrossTarget,
|
||||||
|
|
||||||
pub fn oFileExt(self: &const Target) -> []const u8 {
|
pub fn oFileExt(self: &const Target) []const u8 {
|
||||||
const environ = switch (*self) {
|
const environ = switch (*self) {
|
||||||
Target.Native => builtin.environ,
|
Target.Native => builtin.environ,
|
||||||
Target.Cross => |t| t.environ,
|
Target.Cross => |t| t.environ,
|
||||||
@ -775,42 +775,42 @@ pub const Target = union(enum) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn exeFileExt(self: &const Target) -> []const u8 {
|
pub fn exeFileExt(self: &const Target) []const u8 {
|
||||||
return switch (self.getOs()) {
|
return switch (self.getOs()) {
|
||||||
builtin.Os.windows => ".exe",
|
builtin.Os.windows => ".exe",
|
||||||
else => "",
|
else => "",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn libFileExt(self: &const Target) -> []const u8 {
|
pub fn libFileExt(self: &const Target) []const u8 {
|
||||||
return switch (self.getOs()) {
|
return switch (self.getOs()) {
|
||||||
builtin.Os.windows => ".lib",
|
builtin.Os.windows => ".lib",
|
||||||
else => ".a",
|
else => ".a",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getOs(self: &const Target) -> builtin.Os {
|
pub fn getOs(self: &const Target) builtin.Os {
|
||||||
return switch (*self) {
|
return switch (*self) {
|
||||||
Target.Native => builtin.os,
|
Target.Native => builtin.os,
|
||||||
Target.Cross => |t| t.os,
|
Target.Cross => |t| t.os,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn isDarwin(self: &const Target) -> bool {
|
pub fn isDarwin(self: &const Target) bool {
|
||||||
return switch (self.getOs()) {
|
return switch (self.getOs()) {
|
||||||
builtin.Os.ios, builtin.Os.macosx => true,
|
builtin.Os.ios, builtin.Os.macosx => true,
|
||||||
else => false,
|
else => false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn isWindows(self: &const Target) -> bool {
|
pub fn isWindows(self: &const Target) bool {
|
||||||
return switch (self.getOs()) {
|
return switch (self.getOs()) {
|
||||||
builtin.Os.windows => true,
|
builtin.Os.windows => true,
|
||||||
else => false,
|
else => false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn wantSharedLibSymLinks(self: &const Target) -> bool {
|
pub fn wantSharedLibSymLinks(self: &const Target) bool {
|
||||||
return !self.isWindows();
|
return !self.isWindows();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -865,58 +865,58 @@ pub const LibExeObjStep = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub fn createSharedLibrary(builder: &Builder, name: []const u8, root_src: ?[]const u8,
|
pub fn createSharedLibrary(builder: &Builder, name: []const u8, root_src: ?[]const u8,
|
||||||
ver: &const Version) -> &LibExeObjStep
|
ver: &const Version) &LibExeObjStep
|
||||||
{
|
{
|
||||||
const self = builder.allocator.create(LibExeObjStep) catch unreachable;
|
const self = builder.allocator.create(LibExeObjStep) catch unreachable;
|
||||||
*self = initExtraArgs(builder, name, root_src, Kind.Lib, false, ver);
|
*self = initExtraArgs(builder, name, root_src, Kind.Lib, false, ver);
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn createCSharedLibrary(builder: &Builder, name: []const u8, version: &const Version) -> &LibExeObjStep {
|
pub fn createCSharedLibrary(builder: &Builder, name: []const u8, version: &const Version) &LibExeObjStep {
|
||||||
const self = builder.allocator.create(LibExeObjStep) catch unreachable;
|
const self = builder.allocator.create(LibExeObjStep) catch unreachable;
|
||||||
*self = initC(builder, name, Kind.Lib, version, false);
|
*self = initC(builder, name, Kind.Lib, version, false);
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn createStaticLibrary(builder: &Builder, name: []const u8, root_src: ?[]const u8) -> &LibExeObjStep {
|
pub fn createStaticLibrary(builder: &Builder, name: []const u8, root_src: ?[]const u8) &LibExeObjStep {
|
||||||
const self = builder.allocator.create(LibExeObjStep) catch unreachable;
|
const self = builder.allocator.create(LibExeObjStep) catch unreachable;
|
||||||
*self = initExtraArgs(builder, name, root_src, Kind.Lib, true, builder.version(0, 0, 0));
|
*self = initExtraArgs(builder, name, root_src, Kind.Lib, true, builder.version(0, 0, 0));
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn createCStaticLibrary(builder: &Builder, name: []const u8) -> &LibExeObjStep {
|
pub fn createCStaticLibrary(builder: &Builder, name: []const u8) &LibExeObjStep {
|
||||||
const self = builder.allocator.create(LibExeObjStep) catch unreachable;
|
const self = builder.allocator.create(LibExeObjStep) catch unreachable;
|
||||||
*self = initC(builder, name, Kind.Lib, builder.version(0, 0, 0), true);
|
*self = initC(builder, name, Kind.Lib, builder.version(0, 0, 0), true);
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn createObject(builder: &Builder, name: []const u8, root_src: []const u8) -> &LibExeObjStep {
|
pub fn createObject(builder: &Builder, name: []const u8, root_src: []const u8) &LibExeObjStep {
|
||||||
const self = builder.allocator.create(LibExeObjStep) catch unreachable;
|
const self = builder.allocator.create(LibExeObjStep) catch unreachable;
|
||||||
*self = initExtraArgs(builder, name, root_src, Kind.Obj, false, builder.version(0, 0, 0));
|
*self = initExtraArgs(builder, name, root_src, Kind.Obj, false, builder.version(0, 0, 0));
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn createCObject(builder: &Builder, name: []const u8, src: []const u8) -> &LibExeObjStep {
|
pub fn createCObject(builder: &Builder, name: []const u8, src: []const u8) &LibExeObjStep {
|
||||||
const self = builder.allocator.create(LibExeObjStep) catch unreachable;
|
const self = builder.allocator.create(LibExeObjStep) catch unreachable;
|
||||||
*self = initC(builder, name, Kind.Obj, builder.version(0, 0, 0), false);
|
*self = initC(builder, name, Kind.Obj, builder.version(0, 0, 0), false);
|
||||||
self.object_src = src;
|
self.object_src = src;
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn createExecutable(builder: &Builder, name: []const u8, root_src: ?[]const u8) -> &LibExeObjStep {
|
pub fn createExecutable(builder: &Builder, name: []const u8, root_src: ?[]const u8) &LibExeObjStep {
|
||||||
const self = builder.allocator.create(LibExeObjStep) catch unreachable;
|
const self = builder.allocator.create(LibExeObjStep) catch unreachable;
|
||||||
*self = initExtraArgs(builder, name, root_src, Kind.Exe, false, builder.version(0, 0, 0));
|
*self = initExtraArgs(builder, name, root_src, Kind.Exe, false, builder.version(0, 0, 0));
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn createCExecutable(builder: &Builder, name: []const u8) -> &LibExeObjStep {
|
pub fn createCExecutable(builder: &Builder, name: []const u8) &LibExeObjStep {
|
||||||
const self = builder.allocator.create(LibExeObjStep) catch unreachable;
|
const self = builder.allocator.create(LibExeObjStep) catch unreachable;
|
||||||
*self = initC(builder, name, Kind.Exe, builder.version(0, 0, 0), false);
|
*self = initC(builder, name, Kind.Exe, builder.version(0, 0, 0), false);
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn initExtraArgs(builder: &Builder, name: []const u8, root_src: ?[]const u8, kind: Kind,
|
fn initExtraArgs(builder: &Builder, name: []const u8, root_src: ?[]const u8, kind: Kind,
|
||||||
static: bool, ver: &const Version) -> LibExeObjStep
|
static: bool, ver: &const Version) LibExeObjStep
|
||||||
{
|
{
|
||||||
var self = LibExeObjStep {
|
var self = LibExeObjStep {
|
||||||
.strip = false,
|
.strip = false,
|
||||||
@ -956,7 +956,7 @@ pub const LibExeObjStep = struct {
|
|||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn initC(builder: &Builder, name: []const u8, kind: Kind, version: &const Version, static: bool) -> LibExeObjStep {
|
fn initC(builder: &Builder, name: []const u8, kind: Kind, version: &const Version, static: bool) LibExeObjStep {
|
||||||
var self = LibExeObjStep {
|
var self = LibExeObjStep {
|
||||||
.builder = builder,
|
.builder = builder,
|
||||||
.name = name,
|
.name = name,
|
||||||
@ -996,7 +996,7 @@ pub const LibExeObjStep = struct {
|
|||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn computeOutFileNames(self: &LibExeObjStep) {
|
fn computeOutFileNames(self: &LibExeObjStep) void {
|
||||||
switch (self.kind) {
|
switch (self.kind) {
|
||||||
Kind.Obj => {
|
Kind.Obj => {
|
||||||
self.out_filename = self.builder.fmt("{}{}", self.name, self.target.oFileExt());
|
self.out_filename = self.builder.fmt("{}{}", self.name, self.target.oFileExt());
|
||||||
@ -1031,7 +1031,7 @@ pub const LibExeObjStep = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn setTarget(self: &LibExeObjStep, target_arch: builtin.Arch, target_os: builtin.Os,
|
pub fn setTarget(self: &LibExeObjStep, target_arch: builtin.Arch, target_os: builtin.Os,
|
||||||
target_environ: builtin.Environ)
|
target_environ: builtin.Environ) void
|
||||||
{
|
{
|
||||||
self.target = Target {
|
self.target = Target {
|
||||||
.Cross = CrossTarget {
|
.Cross = CrossTarget {
|
||||||
@ -1044,16 +1044,16 @@ pub const LibExeObjStep = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO respect this in the C args
|
// TODO respect this in the C args
|
||||||
pub fn setLinkerScriptPath(self: &LibExeObjStep, path: []const u8) {
|
pub fn setLinkerScriptPath(self: &LibExeObjStep, path: []const u8) void {
|
||||||
self.linker_script = path;
|
self.linker_script = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn linkFramework(self: &LibExeObjStep, framework_name: []const u8) {
|
pub fn linkFramework(self: &LibExeObjStep, framework_name: []const u8) void {
|
||||||
assert(self.target.isDarwin());
|
assert(self.target.isDarwin());
|
||||||
self.frameworks.put(framework_name) catch unreachable;
|
self.frameworks.put(framework_name) catch unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn linkLibrary(self: &LibExeObjStep, lib: &LibExeObjStep) {
|
pub fn linkLibrary(self: &LibExeObjStep, lib: &LibExeObjStep) void {
|
||||||
assert(self.kind != Kind.Obj);
|
assert(self.kind != Kind.Obj);
|
||||||
assert(lib.kind == Kind.Lib);
|
assert(lib.kind == Kind.Lib);
|
||||||
|
|
||||||
@ -1074,26 +1074,26 @@ pub const LibExeObjStep = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn linkSystemLibrary(self: &LibExeObjStep, name: []const u8) {
|
pub fn linkSystemLibrary(self: &LibExeObjStep, name: []const u8) void {
|
||||||
assert(self.kind != Kind.Obj);
|
assert(self.kind != Kind.Obj);
|
||||||
self.link_libs.put(name) catch unreachable;
|
self.link_libs.put(name) catch unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addSourceFile(self: &LibExeObjStep, file: []const u8) {
|
pub fn addSourceFile(self: &LibExeObjStep, file: []const u8) void {
|
||||||
assert(self.kind != Kind.Obj);
|
assert(self.kind != Kind.Obj);
|
||||||
assert(!self.is_zig);
|
assert(!self.is_zig);
|
||||||
self.source_files.append(file) catch unreachable;
|
self.source_files.append(file) catch unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setVerboseLink(self: &LibExeObjStep, value: bool) {
|
pub fn setVerboseLink(self: &LibExeObjStep, value: bool) void {
|
||||||
self.verbose_link = value;
|
self.verbose_link = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setBuildMode(self: &LibExeObjStep, mode: builtin.Mode) {
|
pub fn setBuildMode(self: &LibExeObjStep, mode: builtin.Mode) void {
|
||||||
self.build_mode = mode;
|
self.build_mode = mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setOutputPath(self: &LibExeObjStep, file_path: []const u8) {
|
pub fn setOutputPath(self: &LibExeObjStep, file_path: []const u8) void {
|
||||||
self.output_path = file_path;
|
self.output_path = file_path;
|
||||||
|
|
||||||
// catch a common mistake
|
// catch a common mistake
|
||||||
@ -1102,14 +1102,14 @@ pub const LibExeObjStep = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getOutputPath(self: &LibExeObjStep) -> []const u8 {
|
pub fn getOutputPath(self: &LibExeObjStep) []const u8 {
|
||||||
return if (self.output_path) |output_path|
|
return if (self.output_path) |output_path|
|
||||||
output_path
|
output_path
|
||||||
else
|
else
|
||||||
os.path.join(self.builder.allocator, self.builder.cache_root, self.out_filename) catch unreachable;
|
os.path.join(self.builder.allocator, self.builder.cache_root, self.out_filename) catch unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setOutputHPath(self: &LibExeObjStep, file_path: []const u8) {
|
pub fn setOutputHPath(self: &LibExeObjStep, file_path: []const u8) void {
|
||||||
self.output_h_path = file_path;
|
self.output_h_path = file_path;
|
||||||
|
|
||||||
// catch a common mistake
|
// catch a common mistake
|
||||||
@ -1118,24 +1118,24 @@ pub const LibExeObjStep = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getOutputHPath(self: &LibExeObjStep) -> []const u8 {
|
pub fn getOutputHPath(self: &LibExeObjStep) []const u8 {
|
||||||
return if (self.output_h_path) |output_h_path|
|
return if (self.output_h_path) |output_h_path|
|
||||||
output_h_path
|
output_h_path
|
||||||
else
|
else
|
||||||
os.path.join(self.builder.allocator, self.builder.cache_root, self.out_h_filename) catch unreachable;
|
os.path.join(self.builder.allocator, self.builder.cache_root, self.out_h_filename) catch unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addAssemblyFile(self: &LibExeObjStep, path: []const u8) {
|
pub fn addAssemblyFile(self: &LibExeObjStep, path: []const u8) void {
|
||||||
self.assembly_files.append(path) catch unreachable;
|
self.assembly_files.append(path) catch unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addObjectFile(self: &LibExeObjStep, path: []const u8) {
|
pub fn addObjectFile(self: &LibExeObjStep, path: []const u8) void {
|
||||||
assert(self.kind != Kind.Obj);
|
assert(self.kind != Kind.Obj);
|
||||||
|
|
||||||
self.object_files.append(path) catch unreachable;
|
self.object_files.append(path) catch unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addObject(self: &LibExeObjStep, obj: &LibExeObjStep) {
|
pub fn addObject(self: &LibExeObjStep, obj: &LibExeObjStep) void {
|
||||||
assert(obj.kind == Kind.Obj);
|
assert(obj.kind == Kind.Obj);
|
||||||
assert(self.kind != Kind.Obj);
|
assert(self.kind != Kind.Obj);
|
||||||
|
|
||||||
@ -1152,15 +1152,15 @@ pub const LibExeObjStep = struct {
|
|||||||
self.include_dirs.append(self.builder.cache_root) catch unreachable;
|
self.include_dirs.append(self.builder.cache_root) catch unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addIncludeDir(self: &LibExeObjStep, path: []const u8) {
|
pub fn addIncludeDir(self: &LibExeObjStep, path: []const u8) void {
|
||||||
self.include_dirs.append(path) catch unreachable;
|
self.include_dirs.append(path) catch unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addLibPath(self: &LibExeObjStep, path: []const u8) {
|
pub fn addLibPath(self: &LibExeObjStep, path: []const u8) void {
|
||||||
self.lib_paths.append(path) catch unreachable;
|
self.lib_paths.append(path) catch unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addPackagePath(self: &LibExeObjStep, name: []const u8, pkg_index_path: []const u8) {
|
pub fn addPackagePath(self: &LibExeObjStep, name: []const u8, pkg_index_path: []const u8) void {
|
||||||
assert(self.is_zig);
|
assert(self.is_zig);
|
||||||
|
|
||||||
self.packages.append(Pkg {
|
self.packages.append(Pkg {
|
||||||
@ -1169,23 +1169,23 @@ pub const LibExeObjStep = struct {
|
|||||||
}) catch unreachable;
|
}) catch unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addCompileFlags(self: &LibExeObjStep, flags: []const []const u8) {
|
pub fn addCompileFlags(self: &LibExeObjStep, flags: []const []const u8) void {
|
||||||
for (flags) |flag| {
|
for (flags) |flag| {
|
||||||
self.cflags.append(flag) catch unreachable;
|
self.cflags.append(flag) catch unreachable;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setNoStdLib(self: &LibExeObjStep, disable: bool) {
|
pub fn setNoStdLib(self: &LibExeObjStep, disable: bool) void {
|
||||||
assert(!self.is_zig);
|
assert(!self.is_zig);
|
||||||
self.disable_libc = disable;
|
self.disable_libc = disable;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make(step: &Step) -> %void {
|
fn make(step: &Step) %void {
|
||||||
const self = @fieldParentPtr(LibExeObjStep, "step", step);
|
const self = @fieldParentPtr(LibExeObjStep, "step", step);
|
||||||
return if (self.is_zig) self.makeZig() else self.makeC();
|
return if (self.is_zig) self.makeZig() else self.makeC();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn makeZig(self: &LibExeObjStep) -> %void {
|
fn makeZig(self: &LibExeObjStep) %void {
|
||||||
const builder = self.builder;
|
const builder = self.builder;
|
||||||
|
|
||||||
assert(self.is_zig);
|
assert(self.is_zig);
|
||||||
@ -1351,7 +1351,7 @@ pub const LibExeObjStep = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn appendCompileFlags(self: &LibExeObjStep, args: &ArrayList([]const u8)) {
|
fn appendCompileFlags(self: &LibExeObjStep, args: &ArrayList([]const u8)) void {
|
||||||
if (!self.strip) {
|
if (!self.strip) {
|
||||||
args.append("-g") catch unreachable;
|
args.append("-g") catch unreachable;
|
||||||
}
|
}
|
||||||
@ -1396,7 +1396,7 @@ pub const LibExeObjStep = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn makeC(self: &LibExeObjStep) -> %void {
|
fn makeC(self: &LibExeObjStep) %void {
|
||||||
const builder = self.builder;
|
const builder = self.builder;
|
||||||
|
|
||||||
const cc = builder.getCCExe();
|
const cc = builder.getCCExe();
|
||||||
@ -1635,7 +1635,7 @@ pub const TestStep = struct {
|
|||||||
target: Target,
|
target: Target,
|
||||||
exec_cmd_args: ?[]const ?[]const u8,
|
exec_cmd_args: ?[]const ?[]const u8,
|
||||||
|
|
||||||
pub fn init(builder: &Builder, root_src: []const u8) -> TestStep {
|
pub fn init(builder: &Builder, root_src: []const u8) TestStep {
|
||||||
const step_name = builder.fmt("test {}", root_src);
|
const step_name = builder.fmt("test {}", root_src);
|
||||||
return TestStep {
|
return TestStep {
|
||||||
.step = Step.init(step_name, builder.allocator, make),
|
.step = Step.init(step_name, builder.allocator, make),
|
||||||
@ -1651,28 +1651,28 @@ pub const TestStep = struct {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setVerbose(self: &TestStep, value: bool) {
|
pub fn setVerbose(self: &TestStep, value: bool) void {
|
||||||
self.verbose = value;
|
self.verbose = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setBuildMode(self: &TestStep, mode: builtin.Mode) {
|
pub fn setBuildMode(self: &TestStep, mode: builtin.Mode) void {
|
||||||
self.build_mode = mode;
|
self.build_mode = mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn linkSystemLibrary(self: &TestStep, name: []const u8) {
|
pub fn linkSystemLibrary(self: &TestStep, name: []const u8) void {
|
||||||
self.link_libs.put(name) catch unreachable;
|
self.link_libs.put(name) catch unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setNamePrefix(self: &TestStep, text: []const u8) {
|
pub fn setNamePrefix(self: &TestStep, text: []const u8) void {
|
||||||
self.name_prefix = text;
|
self.name_prefix = text;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setFilter(self: &TestStep, text: ?[]const u8) {
|
pub fn setFilter(self: &TestStep, text: ?[]const u8) void {
|
||||||
self.filter = text;
|
self.filter = text;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setTarget(self: &TestStep, target_arch: builtin.Arch, target_os: builtin.Os,
|
pub fn setTarget(self: &TestStep, target_arch: builtin.Arch, target_os: builtin.Os,
|
||||||
target_environ: builtin.Environ)
|
target_environ: builtin.Environ) void
|
||||||
{
|
{
|
||||||
self.target = Target {
|
self.target = Target {
|
||||||
.Cross = CrossTarget {
|
.Cross = CrossTarget {
|
||||||
@ -1683,11 +1683,11 @@ pub const TestStep = struct {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setExecCmd(self: &TestStep, args: []const ?[]const u8) {
|
pub fn setExecCmd(self: &TestStep, args: []const ?[]const u8) void {
|
||||||
self.exec_cmd_args = args;
|
self.exec_cmd_args = args;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make(step: &Step) -> %void {
|
fn make(step: &Step) %void {
|
||||||
const self = @fieldParentPtr(TestStep, "step", step);
|
const self = @fieldParentPtr(TestStep, "step", step);
|
||||||
const builder = self.builder;
|
const builder = self.builder;
|
||||||
|
|
||||||
@ -1781,7 +1781,7 @@ pub const CommandStep = struct {
|
|||||||
|
|
||||||
/// ::argv is copied.
|
/// ::argv is copied.
|
||||||
pub fn create(builder: &Builder, cwd: ?[]const u8, env_map: &const BufMap,
|
pub fn create(builder: &Builder, cwd: ?[]const u8, env_map: &const BufMap,
|
||||||
argv: []const []const u8) -> &CommandStep
|
argv: []const []const u8) &CommandStep
|
||||||
{
|
{
|
||||||
const self = builder.allocator.create(CommandStep) catch unreachable;
|
const self = builder.allocator.create(CommandStep) catch unreachable;
|
||||||
*self = CommandStep {
|
*self = CommandStep {
|
||||||
@ -1796,7 +1796,7 @@ pub const CommandStep = struct {
|
|||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make(step: &Step) -> %void {
|
fn make(step: &Step) %void {
|
||||||
const self = @fieldParentPtr(CommandStep, "step", step);
|
const self = @fieldParentPtr(CommandStep, "step", step);
|
||||||
|
|
||||||
const cwd = if (self.cwd) |cwd| self.builder.pathFromRoot(cwd) else self.builder.build_root;
|
const cwd = if (self.cwd) |cwd| self.builder.pathFromRoot(cwd) else self.builder.build_root;
|
||||||
@ -1812,7 +1812,7 @@ const InstallArtifactStep = struct {
|
|||||||
|
|
||||||
const Self = this;
|
const Self = this;
|
||||||
|
|
||||||
pub fn create(builder: &Builder, artifact: &LibExeObjStep) -> &Self {
|
pub fn create(builder: &Builder, artifact: &LibExeObjStep) &Self {
|
||||||
const self = builder.allocator.create(Self) catch unreachable;
|
const self = builder.allocator.create(Self) catch unreachable;
|
||||||
const dest_dir = switch (artifact.kind) {
|
const dest_dir = switch (artifact.kind) {
|
||||||
LibExeObjStep.Kind.Obj => unreachable,
|
LibExeObjStep.Kind.Obj => unreachable,
|
||||||
@ -1836,7 +1836,7 @@ const InstallArtifactStep = struct {
|
|||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make(step: &Step) -> %void {
|
fn make(step: &Step) %void {
|
||||||
const self = @fieldParentPtr(Self, "step", step);
|
const self = @fieldParentPtr(Self, "step", step);
|
||||||
const builder = self.builder;
|
const builder = self.builder;
|
||||||
|
|
||||||
@ -1859,7 +1859,7 @@ pub const InstallFileStep = struct {
|
|||||||
src_path: []const u8,
|
src_path: []const u8,
|
||||||
dest_path: []const u8,
|
dest_path: []const u8,
|
||||||
|
|
||||||
pub fn init(builder: &Builder, src_path: []const u8, dest_path: []const u8) -> InstallFileStep {
|
pub fn init(builder: &Builder, src_path: []const u8, dest_path: []const u8) InstallFileStep {
|
||||||
return InstallFileStep {
|
return InstallFileStep {
|
||||||
.builder = builder,
|
.builder = builder,
|
||||||
.step = Step.init(builder.fmt("install {}", src_path), builder.allocator, make),
|
.step = Step.init(builder.fmt("install {}", src_path), builder.allocator, make),
|
||||||
@ -1868,7 +1868,7 @@ pub const InstallFileStep = struct {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make(step: &Step) -> %void {
|
fn make(step: &Step) %void {
|
||||||
const self = @fieldParentPtr(InstallFileStep, "step", step);
|
const self = @fieldParentPtr(InstallFileStep, "step", step);
|
||||||
try self.builder.copyFile(self.src_path, self.dest_path);
|
try self.builder.copyFile(self.src_path, self.dest_path);
|
||||||
}
|
}
|
||||||
@ -1880,7 +1880,7 @@ pub const WriteFileStep = struct {
|
|||||||
file_path: []const u8,
|
file_path: []const u8,
|
||||||
data: []const u8,
|
data: []const u8,
|
||||||
|
|
||||||
pub fn init(builder: &Builder, file_path: []const u8, data: []const u8) -> WriteFileStep {
|
pub fn init(builder: &Builder, file_path: []const u8, data: []const u8) WriteFileStep {
|
||||||
return WriteFileStep {
|
return WriteFileStep {
|
||||||
.builder = builder,
|
.builder = builder,
|
||||||
.step = Step.init(builder.fmt("writefile {}", file_path), builder.allocator, make),
|
.step = Step.init(builder.fmt("writefile {}", file_path), builder.allocator, make),
|
||||||
@ -1889,7 +1889,7 @@ pub const WriteFileStep = struct {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make(step: &Step) -> %void {
|
fn make(step: &Step) %void {
|
||||||
const self = @fieldParentPtr(WriteFileStep, "step", step);
|
const self = @fieldParentPtr(WriteFileStep, "step", step);
|
||||||
const full_path = self.builder.pathFromRoot(self.file_path);
|
const full_path = self.builder.pathFromRoot(self.file_path);
|
||||||
const full_path_dir = os.path.dirname(full_path);
|
const full_path_dir = os.path.dirname(full_path);
|
||||||
@ -1909,7 +1909,7 @@ pub const LogStep = struct {
|
|||||||
builder: &Builder,
|
builder: &Builder,
|
||||||
data: []const u8,
|
data: []const u8,
|
||||||
|
|
||||||
pub fn init(builder: &Builder, data: []const u8) -> LogStep {
|
pub fn init(builder: &Builder, data: []const u8) LogStep {
|
||||||
return LogStep {
|
return LogStep {
|
||||||
.builder = builder,
|
.builder = builder,
|
||||||
.step = Step.init(builder.fmt("log {}", data), builder.allocator, make),
|
.step = Step.init(builder.fmt("log {}", data), builder.allocator, make),
|
||||||
@ -1917,7 +1917,7 @@ pub const LogStep = struct {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make(step: &Step) -> %void {
|
fn make(step: &Step) %void {
|
||||||
const self = @fieldParentPtr(LogStep, "step", step);
|
const self = @fieldParentPtr(LogStep, "step", step);
|
||||||
warn("{}", self.data);
|
warn("{}", self.data);
|
||||||
}
|
}
|
||||||
@ -1928,7 +1928,7 @@ pub const RemoveDirStep = struct {
|
|||||||
builder: &Builder,
|
builder: &Builder,
|
||||||
dir_path: []const u8,
|
dir_path: []const u8,
|
||||||
|
|
||||||
pub fn init(builder: &Builder, dir_path: []const u8) -> RemoveDirStep {
|
pub fn init(builder: &Builder, dir_path: []const u8) RemoveDirStep {
|
||||||
return RemoveDirStep {
|
return RemoveDirStep {
|
||||||
.builder = builder,
|
.builder = builder,
|
||||||
.step = Step.init(builder.fmt("RemoveDir {}", dir_path), builder.allocator, make),
|
.step = Step.init(builder.fmt("RemoveDir {}", dir_path), builder.allocator, make),
|
||||||
@ -1936,7 +1936,7 @@ pub const RemoveDirStep = struct {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make(step: &Step) -> %void {
|
fn make(step: &Step) %void {
|
||||||
const self = @fieldParentPtr(RemoveDirStep, "step", step);
|
const self = @fieldParentPtr(RemoveDirStep, "step", step);
|
||||||
|
|
||||||
const full_path = self.builder.pathFromRoot(self.dir_path);
|
const full_path = self.builder.pathFromRoot(self.dir_path);
|
||||||
@ -1949,12 +1949,12 @@ pub const RemoveDirStep = struct {
|
|||||||
|
|
||||||
pub const Step = struct {
|
pub const Step = struct {
|
||||||
name: []const u8,
|
name: []const u8,
|
||||||
makeFn: fn(self: &Step) -> %void,
|
makeFn: fn(self: &Step) %void,
|
||||||
dependencies: ArrayList(&Step),
|
dependencies: ArrayList(&Step),
|
||||||
loop_flag: bool,
|
loop_flag: bool,
|
||||||
done_flag: bool,
|
done_flag: bool,
|
||||||
|
|
||||||
pub fn init(name: []const u8, allocator: &Allocator, makeFn: fn (&Step)->%void) -> Step {
|
pub fn init(name: []const u8, allocator: &Allocator, makeFn: fn (&Step)%void) Step {
|
||||||
return Step {
|
return Step {
|
||||||
.name = name,
|
.name = name,
|
||||||
.makeFn = makeFn,
|
.makeFn = makeFn,
|
||||||
@ -1963,11 +1963,11 @@ pub const Step = struct {
|
|||||||
.done_flag = false,
|
.done_flag = false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
pub fn initNoOp(name: []const u8, allocator: &Allocator) -> Step {
|
pub fn initNoOp(name: []const u8, allocator: &Allocator) Step {
|
||||||
return init(name, allocator, makeNoOp);
|
return init(name, allocator, makeNoOp);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn make(self: &Step) -> %void {
|
pub fn make(self: &Step) %void {
|
||||||
if (self.done_flag)
|
if (self.done_flag)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -1975,15 +1975,15 @@ pub const Step = struct {
|
|||||||
self.done_flag = true;
|
self.done_flag = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dependOn(self: &Step, other: &Step) {
|
pub fn dependOn(self: &Step, other: &Step) void {
|
||||||
self.dependencies.append(other) catch unreachable;
|
self.dependencies.append(other) catch unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn makeNoOp(self: &Step) -> %void {}
|
fn makeNoOp(self: &Step) %void {}
|
||||||
};
|
};
|
||||||
|
|
||||||
fn doAtomicSymLinks(allocator: &Allocator, output_path: []const u8, filename_major_only: []const u8,
|
fn doAtomicSymLinks(allocator: &Allocator, output_path: []const u8, filename_major_only: []const u8,
|
||||||
filename_name_only: []const u8) -> %void
|
filename_name_only: []const u8) %void
|
||||||
{
|
{
|
||||||
const out_dir = os.path.dirname(output_path);
|
const out_dir = os.path.dirname(output_path);
|
||||||
const out_basename = os.path.basename(output_path);
|
const out_basename = os.path.basename(output_path);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
extern "c" fn __error() -> &c_int;
|
extern "c" fn __error() &c_int;
|
||||||
pub extern "c" fn _NSGetExecutablePath(buf: &u8, bufsize: &u32) -> c_int;
|
pub extern "c" fn _NSGetExecutablePath(buf: &u8, bufsize: &u32) c_int;
|
||||||
|
|
||||||
|
|
||||||
pub use @import("../os/darwin_errno.zig");
|
pub use @import("../os/darwin_errno.zig");
|
||||||
@ -41,7 +41,7 @@ pub const sigset_t = u32;
|
|||||||
|
|
||||||
/// Renamed from `sigaction` to `Sigaction` to avoid conflict with function name.
|
/// Renamed from `sigaction` to `Sigaction` to avoid conflict with function name.
|
||||||
pub const Sigaction = extern struct {
|
pub const Sigaction = extern struct {
|
||||||
handler: extern fn(c_int),
|
handler: extern fn(c_int)void,
|
||||||
sa_mask: sigset_t,
|
sa_mask: sigset_t,
|
||||||
sa_flags: c_int,
|
sa_flags: c_int,
|
||||||
};
|
};
|
||||||
|
@ -9,43 +9,43 @@ pub use switch(builtin.os) {
|
|||||||
};
|
};
|
||||||
const empty_import = @import("../empty.zig");
|
const empty_import = @import("../empty.zig");
|
||||||
|
|
||||||
pub extern "c" fn abort() -> noreturn;
|
pub extern "c" fn abort() noreturn;
|
||||||
pub extern "c" fn exit(code: c_int) -> noreturn;
|
pub extern "c" fn exit(code: c_int) noreturn;
|
||||||
pub extern "c" fn isatty(fd: c_int) -> c_int;
|
pub extern "c" fn isatty(fd: c_int) c_int;
|
||||||
pub extern "c" fn close(fd: c_int) -> c_int;
|
pub extern "c" fn close(fd: c_int) c_int;
|
||||||
pub extern "c" fn fstat(fd: c_int, buf: &Stat) -> c_int;
|
pub extern "c" fn fstat(fd: c_int, buf: &Stat) c_int;
|
||||||
pub extern "c" fn @"fstat$INODE64"(fd: c_int, buf: &Stat) -> c_int;
|
pub extern "c" fn @"fstat$INODE64"(fd: c_int, buf: &Stat) c_int;
|
||||||
pub extern "c" fn lseek(fd: c_int, offset: isize, whence: c_int) -> isize;
|
pub extern "c" fn lseek(fd: c_int, offset: isize, whence: c_int) isize;
|
||||||
pub extern "c" fn open(path: &const u8, oflag: c_int, ...) -> c_int;
|
pub extern "c" fn open(path: &const u8, oflag: c_int, ...) c_int;
|
||||||
pub extern "c" fn raise(sig: c_int) -> c_int;
|
pub extern "c" fn raise(sig: c_int) c_int;
|
||||||
pub extern "c" fn read(fd: c_int, buf: &c_void, nbyte: usize) -> isize;
|
pub extern "c" fn read(fd: c_int, buf: &c_void, nbyte: usize) isize;
|
||||||
pub extern "c" fn stat(noalias path: &const u8, noalias buf: &Stat) -> c_int;
|
pub extern "c" fn stat(noalias path: &const u8, noalias buf: &Stat) c_int;
|
||||||
pub extern "c" fn write(fd: c_int, buf: &const c_void, nbyte: usize) -> c_int;
|
pub extern "c" fn write(fd: c_int, buf: &const c_void, nbyte: usize) c_int;
|
||||||
pub extern "c" fn mmap(addr: ?&c_void, len: usize, prot: c_int, flags: c_int,
|
pub extern "c" fn mmap(addr: ?&c_void, len: usize, prot: c_int, flags: c_int,
|
||||||
fd: c_int, offset: isize) -> ?&c_void;
|
fd: c_int, offset: isize) ?&c_void;
|
||||||
pub extern "c" fn munmap(addr: &c_void, len: usize) -> c_int;
|
pub extern "c" fn munmap(addr: &c_void, len: usize) c_int;
|
||||||
pub extern "c" fn unlink(path: &const u8) -> c_int;
|
pub extern "c" fn unlink(path: &const u8) c_int;
|
||||||
pub extern "c" fn getcwd(buf: &u8, size: usize) -> ?&u8;
|
pub extern "c" fn getcwd(buf: &u8, size: usize) ?&u8;
|
||||||
pub extern "c" fn waitpid(pid: c_int, stat_loc: &c_int, options: c_int) -> c_int;
|
pub extern "c" fn waitpid(pid: c_int, stat_loc: &c_int, options: c_int) c_int;
|
||||||
pub extern "c" fn fork() -> c_int;
|
pub extern "c" fn fork() c_int;
|
||||||
pub extern "c" fn pipe(fds: &c_int) -> c_int;
|
pub extern "c" fn pipe(fds: &c_int) c_int;
|
||||||
pub extern "c" fn mkdir(path: &const u8, mode: c_uint) -> c_int;
|
pub extern "c" fn mkdir(path: &const u8, mode: c_uint) c_int;
|
||||||
pub extern "c" fn symlink(existing: &const u8, new: &const u8) -> c_int;
|
pub extern "c" fn symlink(existing: &const u8, new: &const u8) c_int;
|
||||||
pub extern "c" fn rename(old: &const u8, new: &const u8) -> c_int;
|
pub extern "c" fn rename(old: &const u8, new: &const u8) c_int;
|
||||||
pub extern "c" fn chdir(path: &const u8) -> c_int;
|
pub extern "c" fn chdir(path: &const u8) c_int;
|
||||||
pub extern "c" fn execve(path: &const u8, argv: &const ?&const u8,
|
pub extern "c" fn execve(path: &const u8, argv: &const ?&const u8,
|
||||||
envp: &const ?&const u8) -> c_int;
|
envp: &const ?&const u8) c_int;
|
||||||
pub extern "c" fn dup(fd: c_int) -> c_int;
|
pub extern "c" fn dup(fd: c_int) c_int;
|
||||||
pub extern "c" fn dup2(old_fd: c_int, new_fd: c_int) -> c_int;
|
pub extern "c" fn dup2(old_fd: c_int, new_fd: c_int) c_int;
|
||||||
pub extern "c" fn readlink(noalias path: &const u8, noalias buf: &u8, bufsize: usize) -> isize;
|
pub extern "c" fn readlink(noalias path: &const u8, noalias buf: &u8, bufsize: usize) isize;
|
||||||
pub extern "c" fn realpath(noalias file_name: &const u8, noalias resolved_name: &u8) -> ?&u8;
|
pub extern "c" fn realpath(noalias file_name: &const u8, noalias resolved_name: &u8) ?&u8;
|
||||||
pub extern "c" fn sigprocmask(how: c_int, noalias set: &const sigset_t, noalias oset: ?&sigset_t) -> c_int;
|
pub extern "c" fn sigprocmask(how: c_int, noalias set: &const sigset_t, noalias oset: ?&sigset_t) c_int;
|
||||||
pub extern "c" fn sigaction(sig: c_int, noalias act: &const Sigaction, noalias oact: ?&Sigaction) -> c_int;
|
pub extern "c" fn sigaction(sig: c_int, noalias act: &const Sigaction, noalias oact: ?&Sigaction) c_int;
|
||||||
pub extern "c" fn nanosleep(rqtp: &const timespec, rmtp: ?×pec) -> c_int;
|
pub extern "c" fn nanosleep(rqtp: &const timespec, rmtp: ?×pec) c_int;
|
||||||
pub extern "c" fn setreuid(ruid: c_uint, euid: c_uint) -> c_int;
|
pub extern "c" fn setreuid(ruid: c_uint, euid: c_uint) c_int;
|
||||||
pub extern "c" fn setregid(rgid: c_uint, egid: c_uint) -> c_int;
|
pub extern "c" fn setregid(rgid: c_uint, egid: c_uint) c_int;
|
||||||
|
|
||||||
pub extern "c" fn malloc(usize) -> ?&c_void;
|
pub extern "c" fn malloc(usize) ?&c_void;
|
||||||
pub extern "c" fn realloc(&c_void, usize) -> ?&c_void;
|
pub extern "c" fn realloc(&c_void, usize) ?&c_void;
|
||||||
pub extern "c" fn free(&c_void);
|
pub extern "c" fn free(&c_void) void;
|
||||||
pub extern "c" fn posix_memalign(memptr: &&c_void, alignment: usize, size: usize) -> c_int;
|
pub extern "c" fn posix_memalign(memptr: &&c_void, alignment: usize, size: usize) c_int;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
pub use @import("../os/linux_errno.zig");
|
pub use @import("../os/linux_errno.zig");
|
||||||
|
|
||||||
pub extern "c" fn getrandom(buf_ptr: &u8, buf_len: usize, flags: c_uint) -> c_int;
|
pub extern "c" fn getrandom(buf_ptr: &u8, buf_len: usize, flags: c_uint) c_int;
|
||||||
extern "c" fn __errno_location() -> &c_int;
|
extern "c" fn __errno_location() &c_int;
|
||||||
pub const _errno = __errno_location;
|
pub const _errno = __errno_location;
|
||||||
|
@ -1 +1 @@
|
|||||||
pub extern "c" fn _errno() -> &c_int;
|
pub extern "c" fn _errno() &c_int;
|
||||||
|
@ -9,7 +9,7 @@ const RoundParam = struct {
|
|||||||
a: usize, b: usize, c: usize, d: usize, x: usize, y: usize,
|
a: usize, b: usize, c: usize, d: usize, x: usize, y: usize,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn Rp(a: usize, b: usize, c: usize, d: usize, x: usize, y: usize) -> RoundParam {
|
fn Rp(a: usize, b: usize, c: usize, d: usize, x: usize, y: usize) RoundParam {
|
||||||
return RoundParam { .a = a, .b = b, .c = c, .d = d, .x = x, .y = y, };
|
return RoundParam { .a = a, .b = b, .c = c, .d = d, .x = x, .y = y, };
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -19,7 +19,7 @@ fn Rp(a: usize, b: usize, c: usize, d: usize, x: usize, y: usize) -> RoundParam
|
|||||||
pub const Blake2s224 = Blake2s(224);
|
pub const Blake2s224 = Blake2s(224);
|
||||||
pub const Blake2s256 = Blake2s(256);
|
pub const Blake2s256 = Blake2s(256);
|
||||||
|
|
||||||
fn Blake2s(comptime out_len: usize) -> type { return struct {
|
fn Blake2s(comptime out_len: usize) type { return struct {
|
||||||
const Self = this;
|
const Self = this;
|
||||||
const block_size = 64;
|
const block_size = 64;
|
||||||
const digest_size = out_len / 8;
|
const digest_size = out_len / 8;
|
||||||
@ -48,7 +48,7 @@ fn Blake2s(comptime out_len: usize) -> type { return struct {
|
|||||||
buf: [64]u8,
|
buf: [64]u8,
|
||||||
buf_len: u8,
|
buf_len: u8,
|
||||||
|
|
||||||
pub fn init() -> Self {
|
pub fn init() Self {
|
||||||
debug.assert(8 <= out_len and out_len <= 512);
|
debug.assert(8 <= out_len and out_len <= 512);
|
||||||
|
|
||||||
var s: Self = undefined;
|
var s: Self = undefined;
|
||||||
@ -56,7 +56,7 @@ fn Blake2s(comptime out_len: usize) -> type { return struct {
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reset(d: &Self) {
|
pub fn reset(d: &Self) void {
|
||||||
mem.copy(u32, d.h[0..], iv[0..]);
|
mem.copy(u32, d.h[0..], iv[0..]);
|
||||||
|
|
||||||
// No key plus default parameters
|
// No key plus default parameters
|
||||||
@ -65,13 +65,13 @@ fn Blake2s(comptime out_len: usize) -> type { return struct {
|
|||||||
d.buf_len = 0;
|
d.buf_len = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hash(b: []const u8, out: []u8) {
|
pub fn hash(b: []const u8, out: []u8) void {
|
||||||
var d = Self.init();
|
var d = Self.init();
|
||||||
d.update(b);
|
d.update(b);
|
||||||
d.final(out);
|
d.final(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update(d: &Self, b: []const u8) {
|
pub fn update(d: &Self, b: []const u8) void {
|
||||||
var off: usize = 0;
|
var off: usize = 0;
|
||||||
|
|
||||||
// Partial buffer exists from previous update. Copy into buffer then hash.
|
// Partial buffer exists from previous update. Copy into buffer then hash.
|
||||||
@ -94,7 +94,7 @@ fn Blake2s(comptime out_len: usize) -> type { return struct {
|
|||||||
d.buf_len += u8(b[off..].len);
|
d.buf_len += u8(b[off..].len);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn final(d: &Self, out: []u8) {
|
pub fn final(d: &Self, out: []u8) void {
|
||||||
debug.assert(out.len >= out_len / 8);
|
debug.assert(out.len >= out_len / 8);
|
||||||
|
|
||||||
mem.set(u8, d.buf[d.buf_len..], 0);
|
mem.set(u8, d.buf[d.buf_len..], 0);
|
||||||
@ -108,7 +108,7 @@ fn Blake2s(comptime out_len: usize) -> type { return struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn round(d: &Self, b: []const u8, last: bool) {
|
fn round(d: &Self, b: []const u8, last: bool) void {
|
||||||
debug.assert(b.len == 64);
|
debug.assert(b.len == 64);
|
||||||
|
|
||||||
var m: [16]u32 = undefined;
|
var m: [16]u32 = undefined;
|
||||||
@ -236,7 +236,7 @@ test "blake2s256 streaming" {
|
|||||||
pub const Blake2b384 = Blake2b(384);
|
pub const Blake2b384 = Blake2b(384);
|
||||||
pub const Blake2b512 = Blake2b(512);
|
pub const Blake2b512 = Blake2b(512);
|
||||||
|
|
||||||
fn Blake2b(comptime out_len: usize) -> type { return struct {
|
fn Blake2b(comptime out_len: usize) type { return struct {
|
||||||
const Self = this;
|
const Self = this;
|
||||||
const block_size = 128;
|
const block_size = 128;
|
||||||
const digest_size = out_len / 8;
|
const digest_size = out_len / 8;
|
||||||
@ -269,7 +269,7 @@ fn Blake2b(comptime out_len: usize) -> type { return struct {
|
|||||||
buf: [128]u8,
|
buf: [128]u8,
|
||||||
buf_len: u8,
|
buf_len: u8,
|
||||||
|
|
||||||
pub fn init() -> Self {
|
pub fn init() Self {
|
||||||
debug.assert(8 <= out_len and out_len <= 512);
|
debug.assert(8 <= out_len and out_len <= 512);
|
||||||
|
|
||||||
var s: Self = undefined;
|
var s: Self = undefined;
|
||||||
@ -277,7 +277,7 @@ fn Blake2b(comptime out_len: usize) -> type { return struct {
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reset(d: &Self) {
|
pub fn reset(d: &Self) void {
|
||||||
mem.copy(u64, d.h[0..], iv[0..]);
|
mem.copy(u64, d.h[0..], iv[0..]);
|
||||||
|
|
||||||
// No key plus default parameters
|
// No key plus default parameters
|
||||||
@ -286,13 +286,13 @@ fn Blake2b(comptime out_len: usize) -> type { return struct {
|
|||||||
d.buf_len = 0;
|
d.buf_len = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hash(b: []const u8, out: []u8) {
|
pub fn hash(b: []const u8, out: []u8) void {
|
||||||
var d = Self.init();
|
var d = Self.init();
|
||||||
d.update(b);
|
d.update(b);
|
||||||
d.final(out);
|
d.final(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update(d: &Self, b: []const u8) {
|
pub fn update(d: &Self, b: []const u8) void {
|
||||||
var off: usize = 0;
|
var off: usize = 0;
|
||||||
|
|
||||||
// Partial buffer exists from previous update. Copy into buffer then hash.
|
// Partial buffer exists from previous update. Copy into buffer then hash.
|
||||||
@ -315,7 +315,7 @@ fn Blake2b(comptime out_len: usize) -> type { return struct {
|
|||||||
d.buf_len += u8(b[off..].len);
|
d.buf_len += u8(b[off..].len);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn final(d: &Self, out: []u8) {
|
pub fn final(d: &Self, out: []u8) void {
|
||||||
mem.set(u8, d.buf[d.buf_len..], 0);
|
mem.set(u8, d.buf[d.buf_len..], 0);
|
||||||
d.t += d.buf_len;
|
d.t += d.buf_len;
|
||||||
d.round(d.buf[0..], true);
|
d.round(d.buf[0..], true);
|
||||||
@ -327,7 +327,7 @@ fn Blake2b(comptime out_len: usize) -> type { return struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn round(d: &Self, b: []const u8, last: bool) {
|
fn round(d: &Self, b: []const u8, last: bool) void {
|
||||||
debug.assert(b.len == 128);
|
debug.assert(b.len == 128);
|
||||||
|
|
||||||
var m: [16]u64 = undefined;
|
var m: [16]u64 = undefined;
|
||||||
|
@ -10,7 +10,7 @@ const RoundParam = struct {
|
|||||||
k: usize, s: u32, t: u32
|
k: usize, s: u32, t: u32
|
||||||
};
|
};
|
||||||
|
|
||||||
fn Rp(a: usize, b: usize, c: usize, d: usize, k: usize, s: u32, t: u32) -> RoundParam {
|
fn Rp(a: usize, b: usize, c: usize, d: usize, k: usize, s: u32, t: u32) RoundParam {
|
||||||
return RoundParam { .a = a, .b = b, .c = c, .d = d, .k = k, .s = s, .t = t };
|
return RoundParam { .a = a, .b = b, .c = c, .d = d, .k = k, .s = s, .t = t };
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25,13 +25,13 @@ pub const Md5 = struct {
|
|||||||
buf_len: u8,
|
buf_len: u8,
|
||||||
total_len: u64,
|
total_len: u64,
|
||||||
|
|
||||||
pub fn init() -> Self {
|
pub fn init() Self {
|
||||||
var d: Self = undefined;
|
var d: Self = undefined;
|
||||||
d.reset();
|
d.reset();
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reset(d: &Self) {
|
pub fn reset(d: &Self) void {
|
||||||
d.s[0] = 0x67452301;
|
d.s[0] = 0x67452301;
|
||||||
d.s[1] = 0xEFCDAB89;
|
d.s[1] = 0xEFCDAB89;
|
||||||
d.s[2] = 0x98BADCFE;
|
d.s[2] = 0x98BADCFE;
|
||||||
@ -40,13 +40,13 @@ pub const Md5 = struct {
|
|||||||
d.total_len = 0;
|
d.total_len = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hash(b: []const u8, out: []u8) {
|
pub fn hash(b: []const u8, out: []u8) void {
|
||||||
var d = Md5.init();
|
var d = Md5.init();
|
||||||
d.update(b);
|
d.update(b);
|
||||||
d.final(out);
|
d.final(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update(d: &Self, b: []const u8) {
|
pub fn update(d: &Self, b: []const u8) void {
|
||||||
var off: usize = 0;
|
var off: usize = 0;
|
||||||
|
|
||||||
// Partial buffer exists from previous update. Copy into buffer then hash.
|
// Partial buffer exists from previous update. Copy into buffer then hash.
|
||||||
@ -71,7 +71,7 @@ pub const Md5 = struct {
|
|||||||
d.total_len +%= b.len;
|
d.total_len +%= b.len;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn final(d: &Self, out: []u8) {
|
pub fn final(d: &Self, out: []u8) void {
|
||||||
debug.assert(out.len >= 16);
|
debug.assert(out.len >= 16);
|
||||||
|
|
||||||
// The buffer here will never be completely full.
|
// The buffer here will never be completely full.
|
||||||
@ -103,7 +103,7 @@ pub const Md5 = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn round(d: &Self, b: []const u8) {
|
fn round(d: &Self, b: []const u8) void {
|
||||||
debug.assert(b.len == 64);
|
debug.assert(b.len == 64);
|
||||||
|
|
||||||
var s: [16]u32 = undefined;
|
var s: [16]u32 = undefined;
|
||||||
|
@ -10,7 +10,7 @@ const RoundParam = struct {
|
|||||||
a: usize, b: usize, c: usize, d: usize, e: usize, i: u32,
|
a: usize, b: usize, c: usize, d: usize, e: usize, i: u32,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn Rp(a: usize, b: usize, c: usize, d: usize, e: usize, i: u32) -> RoundParam {
|
fn Rp(a: usize, b: usize, c: usize, d: usize, e: usize, i: u32) RoundParam {
|
||||||
return RoundParam { .a = a, .b = b, .c = c, .d = d, .e = e, .i = i };
|
return RoundParam { .a = a, .b = b, .c = c, .d = d, .e = e, .i = i };
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25,13 +25,13 @@ pub const Sha1 = struct {
|
|||||||
buf_len: u8,
|
buf_len: u8,
|
||||||
total_len: u64,
|
total_len: u64,
|
||||||
|
|
||||||
pub fn init() -> Self {
|
pub fn init() Self {
|
||||||
var d: Self = undefined;
|
var d: Self = undefined;
|
||||||
d.reset();
|
d.reset();
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reset(d: &Self) {
|
pub fn reset(d: &Self) void {
|
||||||
d.s[0] = 0x67452301;
|
d.s[0] = 0x67452301;
|
||||||
d.s[1] = 0xEFCDAB89;
|
d.s[1] = 0xEFCDAB89;
|
||||||
d.s[2] = 0x98BADCFE;
|
d.s[2] = 0x98BADCFE;
|
||||||
@ -41,13 +41,13 @@ pub const Sha1 = struct {
|
|||||||
d.total_len = 0;
|
d.total_len = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hash(b: []const u8, out: []u8) {
|
pub fn hash(b: []const u8, out: []u8) void {
|
||||||
var d = Sha1.init();
|
var d = Sha1.init();
|
||||||
d.update(b);
|
d.update(b);
|
||||||
d.final(out);
|
d.final(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update(d: &Self, b: []const u8) {
|
pub fn update(d: &Self, b: []const u8) void {
|
||||||
var off: usize = 0;
|
var off: usize = 0;
|
||||||
|
|
||||||
// Partial buffer exists from previous update. Copy into buffer then hash.
|
// Partial buffer exists from previous update. Copy into buffer then hash.
|
||||||
@ -71,7 +71,7 @@ pub const Sha1 = struct {
|
|||||||
d.total_len += b.len;
|
d.total_len += b.len;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn final(d: &Self, out: []u8) {
|
pub fn final(d: &Self, out: []u8) void {
|
||||||
debug.assert(out.len >= 20);
|
debug.assert(out.len >= 20);
|
||||||
|
|
||||||
// The buffer here will never be completely full.
|
// The buffer here will never be completely full.
|
||||||
@ -103,7 +103,7 @@ pub const Sha1 = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn round(d: &Self, b: []const u8) {
|
fn round(d: &Self, b: []const u8) void {
|
||||||
debug.assert(b.len == 64);
|
debug.assert(b.len == 64);
|
||||||
|
|
||||||
var s: [16]u32 = undefined;
|
var s: [16]u32 = undefined;
|
||||||
|
@ -13,7 +13,7 @@ const RoundParam256 = struct {
|
|||||||
i: usize, k: u32,
|
i: usize, k: u32,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn Rp256(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, g: usize, h: usize, i: usize, k: u32) -> RoundParam256 {
|
fn Rp256(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, g: usize, h: usize, i: usize, k: u32) RoundParam256 {
|
||||||
return RoundParam256 { .a = a, .b = b, .c = c, .d = d, .e = e, .f = f, .g = g, .h = h, .i = i, .k = k };
|
return RoundParam256 { .a = a, .b = b, .c = c, .d = d, .e = e, .f = f, .g = g, .h = h, .i = i, .k = k };
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,7 +56,7 @@ const Sha256Params = Sha2Params32 {
|
|||||||
pub const Sha224 = Sha2_32(Sha224Params);
|
pub const Sha224 = Sha2_32(Sha224Params);
|
||||||
pub const Sha256 = Sha2_32(Sha256Params);
|
pub const Sha256 = Sha2_32(Sha256Params);
|
||||||
|
|
||||||
fn Sha2_32(comptime params: Sha2Params32) -> type { return struct {
|
fn Sha2_32(comptime params: Sha2Params32) type { return struct {
|
||||||
const Self = this;
|
const Self = this;
|
||||||
const block_size = 64;
|
const block_size = 64;
|
||||||
const digest_size = params.out_len / 8;
|
const digest_size = params.out_len / 8;
|
||||||
@ -67,13 +67,13 @@ fn Sha2_32(comptime params: Sha2Params32) -> type { return struct {
|
|||||||
buf_len: u8,
|
buf_len: u8,
|
||||||
total_len: u64,
|
total_len: u64,
|
||||||
|
|
||||||
pub fn init() -> Self {
|
pub fn init() Self {
|
||||||
var d: Self = undefined;
|
var d: Self = undefined;
|
||||||
d.reset();
|
d.reset();
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reset(d: &Self) {
|
pub fn reset(d: &Self) void {
|
||||||
d.s[0] = params.iv0;
|
d.s[0] = params.iv0;
|
||||||
d.s[1] = params.iv1;
|
d.s[1] = params.iv1;
|
||||||
d.s[2] = params.iv2;
|
d.s[2] = params.iv2;
|
||||||
@ -86,13 +86,13 @@ fn Sha2_32(comptime params: Sha2Params32) -> type { return struct {
|
|||||||
d.total_len = 0;
|
d.total_len = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hash(b: []const u8, out: []u8) {
|
pub fn hash(b: []const u8, out: []u8) void {
|
||||||
var d = Self.init();
|
var d = Self.init();
|
||||||
d.update(b);
|
d.update(b);
|
||||||
d.final(out);
|
d.final(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update(d: &Self, b: []const u8) {
|
pub fn update(d: &Self, b: []const u8) void {
|
||||||
var off: usize = 0;
|
var off: usize = 0;
|
||||||
|
|
||||||
// Partial buffer exists from previous update. Copy into buffer then hash.
|
// Partial buffer exists from previous update. Copy into buffer then hash.
|
||||||
@ -116,7 +116,7 @@ fn Sha2_32(comptime params: Sha2Params32) -> type { return struct {
|
|||||||
d.total_len += b.len;
|
d.total_len += b.len;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn final(d: &Self, out: []u8) {
|
pub fn final(d: &Self, out: []u8) void {
|
||||||
debug.assert(out.len >= params.out_len / 8);
|
debug.assert(out.len >= params.out_len / 8);
|
||||||
|
|
||||||
// The buffer here will never be completely full.
|
// The buffer here will never be completely full.
|
||||||
@ -151,7 +151,7 @@ fn Sha2_32(comptime params: Sha2Params32) -> type { return struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn round(d: &Self, b: []const u8) {
|
fn round(d: &Self, b: []const u8) void {
|
||||||
debug.assert(b.len == 64);
|
debug.assert(b.len == 64);
|
||||||
|
|
||||||
var s: [64]u32 = undefined;
|
var s: [64]u32 = undefined;
|
||||||
@ -329,7 +329,7 @@ const RoundParam512 = struct {
|
|||||||
i: usize, k: u64,
|
i: usize, k: u64,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn Rp512(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, g: usize, h: usize, i: usize, k: u64) -> RoundParam512 {
|
fn Rp512(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, g: usize, h: usize, i: usize, k: u64) RoundParam512 {
|
||||||
return RoundParam512 { .a = a, .b = b, .c = c, .d = d, .e = e, .f = f, .g = g, .h = h, .i = i, .k = k };
|
return RoundParam512 { .a = a, .b = b, .c = c, .d = d, .e = e, .f = f, .g = g, .h = h, .i = i, .k = k };
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -372,7 +372,7 @@ const Sha512Params = Sha2Params64 {
|
|||||||
pub const Sha384 = Sha2_64(Sha384Params);
|
pub const Sha384 = Sha2_64(Sha384Params);
|
||||||
pub const Sha512 = Sha2_64(Sha512Params);
|
pub const Sha512 = Sha2_64(Sha512Params);
|
||||||
|
|
||||||
fn Sha2_64(comptime params: Sha2Params64) -> type { return struct {
|
fn Sha2_64(comptime params: Sha2Params64) type { return struct {
|
||||||
const Self = this;
|
const Self = this;
|
||||||
const block_size = 128;
|
const block_size = 128;
|
||||||
const digest_size = params.out_len / 8;
|
const digest_size = params.out_len / 8;
|
||||||
@ -383,13 +383,13 @@ fn Sha2_64(comptime params: Sha2Params64) -> type { return struct {
|
|||||||
buf_len: u8,
|
buf_len: u8,
|
||||||
total_len: u128,
|
total_len: u128,
|
||||||
|
|
||||||
pub fn init() -> Self {
|
pub fn init() Self {
|
||||||
var d: Self = undefined;
|
var d: Self = undefined;
|
||||||
d.reset();
|
d.reset();
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reset(d: &Self) {
|
pub fn reset(d: &Self) void {
|
||||||
d.s[0] = params.iv0;
|
d.s[0] = params.iv0;
|
||||||
d.s[1] = params.iv1;
|
d.s[1] = params.iv1;
|
||||||
d.s[2] = params.iv2;
|
d.s[2] = params.iv2;
|
||||||
@ -402,13 +402,13 @@ fn Sha2_64(comptime params: Sha2Params64) -> type { return struct {
|
|||||||
d.total_len = 0;
|
d.total_len = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hash(b: []const u8, out: []u8) {
|
pub fn hash(b: []const u8, out: []u8) void {
|
||||||
var d = Self.init();
|
var d = Self.init();
|
||||||
d.update(b);
|
d.update(b);
|
||||||
d.final(out);
|
d.final(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update(d: &Self, b: []const u8) {
|
pub fn update(d: &Self, b: []const u8) void {
|
||||||
var off: usize = 0;
|
var off: usize = 0;
|
||||||
|
|
||||||
// Partial buffer exists from previous update. Copy into buffer then hash.
|
// Partial buffer exists from previous update. Copy into buffer then hash.
|
||||||
@ -432,7 +432,7 @@ fn Sha2_64(comptime params: Sha2Params64) -> type { return struct {
|
|||||||
d.total_len += b.len;
|
d.total_len += b.len;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn final(d: &Self, out: []u8) {
|
pub fn final(d: &Self, out: []u8) void {
|
||||||
debug.assert(out.len >= params.out_len / 8);
|
debug.assert(out.len >= params.out_len / 8);
|
||||||
|
|
||||||
// The buffer here will never be completely full.
|
// The buffer here will never be completely full.
|
||||||
@ -467,7 +467,7 @@ fn Sha2_64(comptime params: Sha2Params64) -> type { return struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn round(d: &Self, b: []const u8) {
|
fn round(d: &Self, b: []const u8) void {
|
||||||
debug.assert(b.len == 128);
|
debug.assert(b.len == 128);
|
||||||
|
|
||||||
var s: [80]u64 = undefined;
|
var s: [80]u64 = undefined;
|
||||||
|
@ -10,7 +10,7 @@ pub const Sha3_256 = Keccak(256, 0x06);
|
|||||||
pub const Sha3_384 = Keccak(384, 0x06);
|
pub const Sha3_384 = Keccak(384, 0x06);
|
||||||
pub const Sha3_512 = Keccak(512, 0x06);
|
pub const Sha3_512 = Keccak(512, 0x06);
|
||||||
|
|
||||||
fn Keccak(comptime bits: usize, comptime delim: u8) -> type { return struct {
|
fn Keccak(comptime bits: usize, comptime delim: u8) type { return struct {
|
||||||
const Self = this;
|
const Self = this;
|
||||||
const block_size = 200;
|
const block_size = 200;
|
||||||
const digest_size = bits / 8;
|
const digest_size = bits / 8;
|
||||||
@ -19,25 +19,25 @@ fn Keccak(comptime bits: usize, comptime delim: u8) -> type { return struct {
|
|||||||
offset: usize,
|
offset: usize,
|
||||||
rate: usize,
|
rate: usize,
|
||||||
|
|
||||||
pub fn init() -> Self {
|
pub fn init() Self {
|
||||||
var d: Self = undefined;
|
var d: Self = undefined;
|
||||||
d.reset();
|
d.reset();
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reset(d: &Self) {
|
pub fn reset(d: &Self) void {
|
||||||
mem.set(u8, d.s[0..], 0);
|
mem.set(u8, d.s[0..], 0);
|
||||||
d.offset = 0;
|
d.offset = 0;
|
||||||
d.rate = 200 - (bits / 4);
|
d.rate = 200 - (bits / 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hash(b: []const u8, out: []u8) {
|
pub fn hash(b: []const u8, out: []u8) void {
|
||||||
var d = Self.init();
|
var d = Self.init();
|
||||||
d.update(b);
|
d.update(b);
|
||||||
d.final(out);
|
d.final(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update(d: &Self, b: []const u8) {
|
pub fn update(d: &Self, b: []const u8) void {
|
||||||
var ip: usize = 0;
|
var ip: usize = 0;
|
||||||
var len = b.len;
|
var len = b.len;
|
||||||
var rate = d.rate - d.offset;
|
var rate = d.rate - d.offset;
|
||||||
@ -62,7 +62,7 @@ fn Keccak(comptime bits: usize, comptime delim: u8) -> type { return struct {
|
|||||||
d.offset = offset + len;
|
d.offset = offset + len;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn final(d: &Self, out: []u8) {
|
pub fn final(d: &Self, out: []u8) void {
|
||||||
// padding
|
// padding
|
||||||
d.s[d.offset] ^= delim;
|
d.s[d.offset] ^= delim;
|
||||||
d.s[d.rate - 1] ^= 0x80;
|
d.s[d.rate - 1] ^= 0x80;
|
||||||
@ -109,7 +109,7 @@ const M5 = []const usize {
|
|||||||
0, 1, 2, 3, 4, 0, 1, 2, 3, 4
|
0, 1, 2, 3, 4, 0, 1, 2, 3, 4
|
||||||
};
|
};
|
||||||
|
|
||||||
fn keccak_f(comptime F: usize, d: []u8) {
|
fn keccak_f(comptime F: usize, d: []u8) void {
|
||||||
debug.assert(d.len == F / 8);
|
debug.assert(d.len == F / 8);
|
||||||
|
|
||||||
const B = F / 25;
|
const B = F / 25;
|
||||||
|
@ -3,7 +3,7 @@ const mem = @import("../mem.zig");
|
|||||||
const fmt = @import("../fmt/index.zig");
|
const fmt = @import("../fmt/index.zig");
|
||||||
|
|
||||||
// Hash using the specified hasher `H` asserting `expected == H(input)`.
|
// Hash using the specified hasher `H` asserting `expected == H(input)`.
|
||||||
pub fn assertEqualHash(comptime Hasher: var, comptime expected: []const u8, input: []const u8) {
|
pub fn assertEqualHash(comptime Hasher: var, comptime expected: []const u8, input: []const u8) void {
|
||||||
var h: [expected.len / 2]u8 = undefined;
|
var h: [expected.len / 2]u8 = undefined;
|
||||||
Hasher.hash(input, h[0..]);
|
Hasher.hash(input, h[0..]);
|
||||||
|
|
||||||
@ -11,7 +11,7 @@ pub fn assertEqualHash(comptime Hasher: var, comptime expected: []const u8, inpu
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Assert `expected` == `input` where `input` is a bytestring.
|
// Assert `expected` == `input` where `input` is a bytestring.
|
||||||
pub fn assertEqual(comptime expected: []const u8, input: []const u8) {
|
pub fn assertEqual(comptime expected: []const u8, input: []const u8) void {
|
||||||
var expected_bytes: [expected.len / 2]u8 = undefined;
|
var expected_bytes: [expected.len / 2]u8 = undefined;
|
||||||
for (expected_bytes) |*r, i| {
|
for (expected_bytes) |*r, i| {
|
||||||
*r = fmt.parseInt(u8, expected[2*i .. 2*i+2], 16) catch unreachable;
|
*r = fmt.parseInt(u8, expected[2*i .. 2*i+2], 16) catch unreachable;
|
||||||
|
@ -18,7 +18,7 @@ const c = @cImport({
|
|||||||
|
|
||||||
const Mb = 1024 * 1024;
|
const Mb = 1024 * 1024;
|
||||||
|
|
||||||
pub fn main() -> %void {
|
pub fn main() %void {
|
||||||
var stdout_file = try std.io.getStdOut();
|
var stdout_file = try std.io.getStdOut();
|
||||||
var stdout_out_stream = std.io.FileOutStream.init(&stdout_file);
|
var stdout_out_stream = std.io.FileOutStream.init(&stdout_file);
|
||||||
const stdout = &stdout_out_stream.stream;
|
const stdout = &stdout_out_stream.stream;
|
||||||
|
16
std/cstr.zig
16
std/cstr.zig
@ -3,13 +3,13 @@ const debug = std.debug;
|
|||||||
const mem = std.mem;
|
const mem = std.mem;
|
||||||
const assert = debug.assert;
|
const assert = debug.assert;
|
||||||
|
|
||||||
pub fn len(ptr: &const u8) -> usize {
|
pub fn len(ptr: &const u8) usize {
|
||||||
var count: usize = 0;
|
var count: usize = 0;
|
||||||
while (ptr[count] != 0) : (count += 1) {}
|
while (ptr[count] != 0) : (count += 1) {}
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cmp(a: &const u8, b: &const u8) -> i8 {
|
pub fn cmp(a: &const u8, b: &const u8) i8 {
|
||||||
var index: usize = 0;
|
var index: usize = 0;
|
||||||
while (a[index] == b[index] and a[index] != 0) : (index += 1) {}
|
while (a[index] == b[index] and a[index] != 0) : (index += 1) {}
|
||||||
if (a[index] > b[index]) {
|
if (a[index] > b[index]) {
|
||||||
@ -21,11 +21,11 @@ pub fn cmp(a: &const u8, b: &const u8) -> i8 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn toSliceConst(str: &const u8) -> []const u8 {
|
pub fn toSliceConst(str: &const u8) []const u8 {
|
||||||
return str[0..len(str)];
|
return str[0..len(str)];
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn toSlice(str: &u8) -> []u8 {
|
pub fn toSlice(str: &u8) []u8 {
|
||||||
return str[0..len(str)];
|
return str[0..len(str)];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,7 +34,7 @@ test "cstr fns" {
|
|||||||
testCStrFnsImpl();
|
testCStrFnsImpl();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn testCStrFnsImpl() {
|
fn testCStrFnsImpl() void {
|
||||||
assert(cmp(c"aoeu", c"aoez") == -1);
|
assert(cmp(c"aoeu", c"aoez") == -1);
|
||||||
assert(len(c"123456789") == 9);
|
assert(len(c"123456789") == 9);
|
||||||
}
|
}
|
||||||
@ -42,7 +42,7 @@ fn testCStrFnsImpl() {
|
|||||||
/// Returns a mutable slice with exactly the same size which is guaranteed to
|
/// Returns a mutable slice with exactly the same size which is guaranteed to
|
||||||
/// have a null byte after it.
|
/// have a null byte after it.
|
||||||
/// Caller owns the returned memory.
|
/// Caller owns the returned memory.
|
||||||
pub fn addNullByte(allocator: &mem.Allocator, slice: []const u8) -> %[]u8 {
|
pub fn addNullByte(allocator: &mem.Allocator, slice: []const u8) %[]u8 {
|
||||||
const result = try allocator.alloc(u8, slice.len + 1);
|
const result = try allocator.alloc(u8, slice.len + 1);
|
||||||
mem.copy(u8, result, slice);
|
mem.copy(u8, result, slice);
|
||||||
result[slice.len] = 0;
|
result[slice.len] = 0;
|
||||||
@ -56,7 +56,7 @@ pub const NullTerminated2DArray = struct {
|
|||||||
|
|
||||||
/// Takes N lists of strings, concatenates the lists together, and adds a null terminator
|
/// Takes N lists of strings, concatenates the lists together, and adds a null terminator
|
||||||
/// Caller must deinit result
|
/// Caller must deinit result
|
||||||
pub fn fromSlices(allocator: &mem.Allocator, slices: []const []const []const u8) -> %NullTerminated2DArray {
|
pub fn fromSlices(allocator: &mem.Allocator, slices: []const []const []const u8) %NullTerminated2DArray {
|
||||||
var new_len: usize = 1; // 1 for the list null
|
var new_len: usize = 1; // 1 for the list null
|
||||||
var byte_count: usize = 0;
|
var byte_count: usize = 0;
|
||||||
for (slices) |slice| {
|
for (slices) |slice| {
|
||||||
@ -96,7 +96,7 @@ pub const NullTerminated2DArray = struct {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: &NullTerminated2DArray) {
|
pub fn deinit(self: &NullTerminated2DArray) void {
|
||||||
const buf = @ptrCast(&u8, self.ptr);
|
const buf = @ptrCast(&u8, self.ptr);
|
||||||
self.allocator.free(buf[0..self.byte_count]);
|
self.allocator.free(buf[0..self.byte_count]);
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ pub const FailingAllocator = struct {
|
|||||||
freed_bytes: usize,
|
freed_bytes: usize,
|
||||||
deallocations: usize,
|
deallocations: usize,
|
||||||
|
|
||||||
pub fn init(allocator: &mem.Allocator, fail_index: usize) -> FailingAllocator {
|
pub fn init(allocator: &mem.Allocator, fail_index: usize) FailingAllocator {
|
||||||
return FailingAllocator {
|
return FailingAllocator {
|
||||||
.internal_allocator = allocator,
|
.internal_allocator = allocator,
|
||||||
.fail_index = fail_index,
|
.fail_index = fail_index,
|
||||||
@ -28,7 +28,7 @@ pub const FailingAllocator = struct {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn alloc(allocator: &mem.Allocator, n: usize, alignment: u29) -> %[]u8 {
|
fn alloc(allocator: &mem.Allocator, n: usize, alignment: u29) %[]u8 {
|
||||||
const self = @fieldParentPtr(FailingAllocator, "allocator", allocator);
|
const self = @fieldParentPtr(FailingAllocator, "allocator", allocator);
|
||||||
if (self.index == self.fail_index) {
|
if (self.index == self.fail_index) {
|
||||||
return error.OutOfMemory;
|
return error.OutOfMemory;
|
||||||
@ -39,7 +39,7 @@ pub const FailingAllocator = struct {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn realloc(allocator: &mem.Allocator, old_mem: []u8, new_size: usize, alignment: u29) -> %[]u8 {
|
fn realloc(allocator: &mem.Allocator, old_mem: []u8, new_size: usize, alignment: u29) %[]u8 {
|
||||||
const self = @fieldParentPtr(FailingAllocator, "allocator", allocator);
|
const self = @fieldParentPtr(FailingAllocator, "allocator", allocator);
|
||||||
if (new_size <= old_mem.len) {
|
if (new_size <= old_mem.len) {
|
||||||
self.freed_bytes += old_mem.len - new_size;
|
self.freed_bytes += old_mem.len - new_size;
|
||||||
@ -55,7 +55,7 @@ pub const FailingAllocator = struct {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn free(allocator: &mem.Allocator, bytes: []u8) {
|
fn free(allocator: &mem.Allocator, bytes: []u8) void {
|
||||||
const self = @fieldParentPtr(FailingAllocator, "allocator", allocator);
|
const self = @fieldParentPtr(FailingAllocator, "allocator", allocator);
|
||||||
self.freed_bytes += bytes.len;
|
self.freed_bytes += bytes.len;
|
||||||
self.deallocations += 1;
|
self.deallocations += 1;
|
||||||
|
@ -25,11 +25,11 @@ error TodoSupportCOFFDebugInfo;
|
|||||||
var stderr_file: io.File = undefined;
|
var stderr_file: io.File = undefined;
|
||||||
var stderr_file_out_stream: io.FileOutStream = undefined;
|
var stderr_file_out_stream: io.FileOutStream = undefined;
|
||||||
var stderr_stream: ?&io.OutStream = null;
|
var stderr_stream: ?&io.OutStream = null;
|
||||||
pub fn warn(comptime fmt: []const u8, args: ...) {
|
pub fn warn(comptime fmt: []const u8, args: ...) void {
|
||||||
const stderr = getStderrStream() catch return;
|
const stderr = getStderrStream() catch return;
|
||||||
stderr.print(fmt, args) catch return;
|
stderr.print(fmt, args) catch return;
|
||||||
}
|
}
|
||||||
fn getStderrStream() -> %&io.OutStream {
|
fn getStderrStream() %&io.OutStream {
|
||||||
if (stderr_stream) |st| {
|
if (stderr_stream) |st| {
|
||||||
return st;
|
return st;
|
||||||
} else {
|
} else {
|
||||||
@ -42,7 +42,7 @@ fn getStderrStream() -> %&io.OutStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var self_debug_info: ?&ElfStackTrace = null;
|
var self_debug_info: ?&ElfStackTrace = null;
|
||||||
pub fn getSelfDebugInfo() -> %&ElfStackTrace {
|
pub fn getSelfDebugInfo() %&ElfStackTrace {
|
||||||
if (self_debug_info) |info| {
|
if (self_debug_info) |info| {
|
||||||
return info;
|
return info;
|
||||||
} else {
|
} else {
|
||||||
@ -53,7 +53,7 @@ pub fn getSelfDebugInfo() -> %&ElfStackTrace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Tries to print the current stack trace to stderr, unbuffered, and ignores any error returned.
|
/// Tries to print the current stack trace to stderr, unbuffered, and ignores any error returned.
|
||||||
pub fn dumpCurrentStackTrace() {
|
pub fn dumpCurrentStackTrace() void {
|
||||||
const stderr = getStderrStream() catch return;
|
const stderr = getStderrStream() catch return;
|
||||||
const debug_info = getSelfDebugInfo() catch |err| {
|
const debug_info = getSelfDebugInfo() catch |err| {
|
||||||
stderr.print("Unable to open debug info: {}\n", @errorName(err)) catch return;
|
stderr.print("Unable to open debug info: {}\n", @errorName(err)) catch return;
|
||||||
@ -67,7 +67,7 @@ pub fn dumpCurrentStackTrace() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Tries to print a stack trace to stderr, unbuffered, and ignores any error returned.
|
/// Tries to print a stack trace to stderr, unbuffered, and ignores any error returned.
|
||||||
pub fn dumpStackTrace(stack_trace: &const builtin.StackTrace) {
|
pub fn dumpStackTrace(stack_trace: &const builtin.StackTrace) void {
|
||||||
const stderr = getStderrStream() catch return;
|
const stderr = getStderrStream() catch return;
|
||||||
const debug_info = getSelfDebugInfo() catch |err| {
|
const debug_info = getSelfDebugInfo() catch |err| {
|
||||||
stderr.print("Unable to open debug info: {}\n", @errorName(err)) catch return;
|
stderr.print("Unable to open debug info: {}\n", @errorName(err)) catch return;
|
||||||
@ -85,7 +85,7 @@ pub fn dumpStackTrace(stack_trace: &const builtin.StackTrace) {
|
|||||||
/// generated, and the `unreachable` statement triggers a panic.
|
/// generated, and the `unreachable` statement triggers a panic.
|
||||||
/// In ReleaseFast and ReleaseSmall modes, calls to this function can be
|
/// In ReleaseFast and ReleaseSmall modes, calls to this function can be
|
||||||
/// optimized away.
|
/// optimized away.
|
||||||
pub fn assert(ok: bool) {
|
pub fn assert(ok: bool) void {
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
// In ReleaseFast test mode, we still want assert(false) to crash, so
|
// In ReleaseFast test mode, we still want assert(false) to crash, so
|
||||||
// we insert an explicit call to @panic instead of unreachable.
|
// we insert an explicit call to @panic instead of unreachable.
|
||||||
@ -100,7 +100,7 @@ pub fn assert(ok: bool) {
|
|||||||
|
|
||||||
/// Call this function when you want to panic if the condition is not true.
|
/// Call this function when you want to panic if the condition is not true.
|
||||||
/// If `ok` is `false`, this function will panic in every release mode.
|
/// If `ok` is `false`, this function will panic in every release mode.
|
||||||
pub fn assertOrPanic(ok: bool) {
|
pub fn assertOrPanic(ok: bool) void {
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
@panic("assertion failure");
|
@panic("assertion failure");
|
||||||
}
|
}
|
||||||
@ -108,7 +108,7 @@ pub fn assertOrPanic(ok: bool) {
|
|||||||
|
|
||||||
var panicking = false;
|
var panicking = false;
|
||||||
/// This is the default panic implementation.
|
/// This is the default panic implementation.
|
||||||
pub fn panic(comptime format: []const u8, args: ...) -> noreturn {
|
pub fn panic(comptime format: []const u8, args: ...) noreturn {
|
||||||
// TODO an intrinsic that labels this as unlikely to be reached
|
// TODO an intrinsic that labels this as unlikely to be reached
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
@ -130,7 +130,7 @@ pub fn panic(comptime format: []const u8, args: ...) -> noreturn {
|
|||||||
os.abort();
|
os.abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn panicWithTrace(trace: &const builtin.StackTrace, comptime format: []const u8, args: ...) -> noreturn {
|
pub fn panicWithTrace(trace: &const builtin.StackTrace, comptime format: []const u8, args: ...) noreturn {
|
||||||
if (panicking) {
|
if (panicking) {
|
||||||
os.abort();
|
os.abort();
|
||||||
} else {
|
} else {
|
||||||
@ -153,7 +153,7 @@ error PathNotFound;
|
|||||||
error InvalidDebugInfo;
|
error InvalidDebugInfo;
|
||||||
|
|
||||||
pub fn writeStackTrace(stack_trace: &const builtin.StackTrace, out_stream: &io.OutStream, allocator: &mem.Allocator,
|
pub fn writeStackTrace(stack_trace: &const builtin.StackTrace, out_stream: &io.OutStream, allocator: &mem.Allocator,
|
||||||
debug_info: &ElfStackTrace, tty_color: bool) -> %void
|
debug_info: &ElfStackTrace, tty_color: bool) %void
|
||||||
{
|
{
|
||||||
var frame_index: usize = undefined;
|
var frame_index: usize = undefined;
|
||||||
var frames_left: usize = undefined;
|
var frames_left: usize = undefined;
|
||||||
@ -175,7 +175,7 @@ pub fn writeStackTrace(stack_trace: &const builtin.StackTrace, out_stream: &io.O
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn writeCurrentStackTrace(out_stream: &io.OutStream, allocator: &mem.Allocator,
|
pub fn writeCurrentStackTrace(out_stream: &io.OutStream, allocator: &mem.Allocator,
|
||||||
debug_info: &ElfStackTrace, tty_color: bool, ignore_frame_count: usize) -> %void
|
debug_info: &ElfStackTrace, tty_color: bool, ignore_frame_count: usize) %void
|
||||||
{
|
{
|
||||||
var ignored_count: usize = 0;
|
var ignored_count: usize = 0;
|
||||||
|
|
||||||
@ -191,7 +191,7 @@ pub fn writeCurrentStackTrace(out_stream: &io.OutStream, allocator: &mem.Allocat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn printSourceAtAddress(debug_info: &ElfStackTrace, out_stream: &io.OutStream, address: usize) -> %void {
|
fn printSourceAtAddress(debug_info: &ElfStackTrace, out_stream: &io.OutStream, address: usize) %void {
|
||||||
if (builtin.os == builtin.Os.windows) {
|
if (builtin.os == builtin.Os.windows) {
|
||||||
return error.UnsupportedDebugInfo;
|
return error.UnsupportedDebugInfo;
|
||||||
}
|
}
|
||||||
@ -232,7 +232,7 @@ fn printSourceAtAddress(debug_info: &ElfStackTrace, out_stream: &io.OutStream, a
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn openSelfDebugInfo(allocator: &mem.Allocator) -> %&ElfStackTrace {
|
pub fn openSelfDebugInfo(allocator: &mem.Allocator) %&ElfStackTrace {
|
||||||
switch (builtin.object_format) {
|
switch (builtin.object_format) {
|
||||||
builtin.ObjectFormat.elf => {
|
builtin.ObjectFormat.elf => {
|
||||||
const st = try allocator.create(ElfStackTrace);
|
const st = try allocator.create(ElfStackTrace);
|
||||||
@ -276,7 +276,7 @@ pub fn openSelfDebugInfo(allocator: &mem.Allocator) -> %&ElfStackTrace {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn printLineFromFile(allocator: &mem.Allocator, out_stream: &io.OutStream, line_info: &const LineInfo) -> %void {
|
fn printLineFromFile(allocator: &mem.Allocator, out_stream: &io.OutStream, line_info: &const LineInfo) %void {
|
||||||
var f = try io.File.openRead(line_info.file_name, allocator);
|
var f = try io.File.openRead(line_info.file_name, allocator);
|
||||||
defer f.close();
|
defer f.close();
|
||||||
// TODO fstat and make sure that the file has the correct size
|
// TODO fstat and make sure that the file has the correct size
|
||||||
@ -320,17 +320,17 @@ pub const ElfStackTrace = struct {
|
|||||||
abbrev_table_list: ArrayList(AbbrevTableHeader),
|
abbrev_table_list: ArrayList(AbbrevTableHeader),
|
||||||
compile_unit_list: ArrayList(CompileUnit),
|
compile_unit_list: ArrayList(CompileUnit),
|
||||||
|
|
||||||
pub fn allocator(self: &const ElfStackTrace) -> &mem.Allocator {
|
pub fn allocator(self: &const ElfStackTrace) &mem.Allocator {
|
||||||
return self.abbrev_table_list.allocator;
|
return self.abbrev_table_list.allocator;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn readString(self: &ElfStackTrace) -> %[]u8 {
|
pub fn readString(self: &ElfStackTrace) %[]u8 {
|
||||||
var in_file_stream = io.FileInStream.init(&self.self_exe_file);
|
var in_file_stream = io.FileInStream.init(&self.self_exe_file);
|
||||||
const in_stream = &in_file_stream.stream;
|
const in_stream = &in_file_stream.stream;
|
||||||
return readStringRaw(self.allocator(), in_stream);
|
return readStringRaw(self.allocator(), in_stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn close(self: &ElfStackTrace) {
|
pub fn close(self: &ElfStackTrace) void {
|
||||||
self.self_exe_file.close();
|
self.self_exe_file.close();
|
||||||
self.elf.close();
|
self.elf.close();
|
||||||
}
|
}
|
||||||
@ -387,7 +387,7 @@ const Constant = struct {
|
|||||||
payload: []u8,
|
payload: []u8,
|
||||||
signed: bool,
|
signed: bool,
|
||||||
|
|
||||||
fn asUnsignedLe(self: &const Constant) -> %u64 {
|
fn asUnsignedLe(self: &const Constant) %u64 {
|
||||||
if (self.payload.len > @sizeOf(u64))
|
if (self.payload.len > @sizeOf(u64))
|
||||||
return error.InvalidDebugInfo;
|
return error.InvalidDebugInfo;
|
||||||
if (self.signed)
|
if (self.signed)
|
||||||
@ -406,7 +406,7 @@ const Die = struct {
|
|||||||
value: FormValue,
|
value: FormValue,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn getAttr(self: &const Die, id: u64) -> ?&const FormValue {
|
fn getAttr(self: &const Die, id: u64) ?&const FormValue {
|
||||||
for (self.attrs.toSliceConst()) |*attr| {
|
for (self.attrs.toSliceConst()) |*attr| {
|
||||||
if (attr.id == id)
|
if (attr.id == id)
|
||||||
return &attr.value;
|
return &attr.value;
|
||||||
@ -414,7 +414,7 @@ const Die = struct {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getAttrAddr(self: &const Die, id: u64) -> %u64 {
|
fn getAttrAddr(self: &const Die, id: u64) %u64 {
|
||||||
const form_value = self.getAttr(id) ?? return error.MissingDebugInfo;
|
const form_value = self.getAttr(id) ?? return error.MissingDebugInfo;
|
||||||
return switch (*form_value) {
|
return switch (*form_value) {
|
||||||
FormValue.Address => |value| value,
|
FormValue.Address => |value| value,
|
||||||
@ -422,7 +422,7 @@ const Die = struct {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getAttrSecOffset(self: &const Die, id: u64) -> %u64 {
|
fn getAttrSecOffset(self: &const Die, id: u64) %u64 {
|
||||||
const form_value = self.getAttr(id) ?? return error.MissingDebugInfo;
|
const form_value = self.getAttr(id) ?? return error.MissingDebugInfo;
|
||||||
return switch (*form_value) {
|
return switch (*form_value) {
|
||||||
FormValue.Const => |value| value.asUnsignedLe(),
|
FormValue.Const => |value| value.asUnsignedLe(),
|
||||||
@ -431,7 +431,7 @@ const Die = struct {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getAttrUnsignedLe(self: &const Die, id: u64) -> %u64 {
|
fn getAttrUnsignedLe(self: &const Die, id: u64) %u64 {
|
||||||
const form_value = self.getAttr(id) ?? return error.MissingDebugInfo;
|
const form_value = self.getAttr(id) ?? return error.MissingDebugInfo;
|
||||||
return switch (*form_value) {
|
return switch (*form_value) {
|
||||||
FormValue.Const => |value| value.asUnsignedLe(),
|
FormValue.Const => |value| value.asUnsignedLe(),
|
||||||
@ -439,7 +439,7 @@ const Die = struct {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getAttrString(self: &const Die, st: &ElfStackTrace, id: u64) -> %[]u8 {
|
fn getAttrString(self: &const Die, st: &ElfStackTrace, id: u64) %[]u8 {
|
||||||
const form_value = self.getAttr(id) ?? return error.MissingDebugInfo;
|
const form_value = self.getAttr(id) ?? return error.MissingDebugInfo;
|
||||||
return switch (*form_value) {
|
return switch (*form_value) {
|
||||||
FormValue.String => |value| value,
|
FormValue.String => |value| value,
|
||||||
@ -462,7 +462,7 @@ const LineInfo = struct {
|
|||||||
file_name: []u8,
|
file_name: []u8,
|
||||||
allocator: &mem.Allocator,
|
allocator: &mem.Allocator,
|
||||||
|
|
||||||
fn deinit(self: &const LineInfo) {
|
fn deinit(self: &const LineInfo) void {
|
||||||
self.allocator.free(self.file_name);
|
self.allocator.free(self.file_name);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -489,7 +489,7 @@ const LineNumberProgram = struct {
|
|||||||
prev_end_sequence: bool,
|
prev_end_sequence: bool,
|
||||||
|
|
||||||
pub fn init(is_stmt: bool, include_dirs: []const []const u8,
|
pub fn init(is_stmt: bool, include_dirs: []const []const u8,
|
||||||
file_entries: &ArrayList(FileEntry), target_address: usize) -> LineNumberProgram
|
file_entries: &ArrayList(FileEntry), target_address: usize) LineNumberProgram
|
||||||
{
|
{
|
||||||
return LineNumberProgram {
|
return LineNumberProgram {
|
||||||
.address = 0,
|
.address = 0,
|
||||||
@ -512,7 +512,7 @@ const LineNumberProgram = struct {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn checkLineMatch(self: &LineNumberProgram) -> %?LineInfo {
|
pub fn checkLineMatch(self: &LineNumberProgram) %?LineInfo {
|
||||||
if (self.target_address >= self.prev_address and self.target_address < self.address) {
|
if (self.target_address >= self.prev_address and self.target_address < self.address) {
|
||||||
const file_entry = if (self.prev_file == 0) {
|
const file_entry = if (self.prev_file == 0) {
|
||||||
return error.MissingDebugInfo;
|
return error.MissingDebugInfo;
|
||||||
@ -544,7 +544,7 @@ const LineNumberProgram = struct {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
fn readStringRaw(allocator: &mem.Allocator, in_stream: &io.InStream) -> %[]u8 {
|
fn readStringRaw(allocator: &mem.Allocator, in_stream: &io.InStream) %[]u8 {
|
||||||
var buf = ArrayList(u8).init(allocator);
|
var buf = ArrayList(u8).init(allocator);
|
||||||
while (true) {
|
while (true) {
|
||||||
const byte = try in_stream.readByte();
|
const byte = try in_stream.readByte();
|
||||||
@ -555,58 +555,58 @@ fn readStringRaw(allocator: &mem.Allocator, in_stream: &io.InStream) -> %[]u8 {
|
|||||||
return buf.toSlice();
|
return buf.toSlice();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getString(st: &ElfStackTrace, offset: u64) -> %[]u8 {
|
fn getString(st: &ElfStackTrace, offset: u64) %[]u8 {
|
||||||
const pos = st.debug_str.offset + offset;
|
const pos = st.debug_str.offset + offset;
|
||||||
try st.self_exe_file.seekTo(pos);
|
try st.self_exe_file.seekTo(pos);
|
||||||
return st.readString();
|
return st.readString();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn readAllocBytes(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) -> %[]u8 {
|
fn readAllocBytes(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) %[]u8 {
|
||||||
const buf = try global_allocator.alloc(u8, size);
|
const buf = try global_allocator.alloc(u8, size);
|
||||||
errdefer global_allocator.free(buf);
|
errdefer global_allocator.free(buf);
|
||||||
if ((try in_stream.read(buf)) < size) return error.EndOfFile;
|
if ((try in_stream.read(buf)) < size) return error.EndOfFile;
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parseFormValueBlockLen(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) -> %FormValue {
|
fn parseFormValueBlockLen(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) %FormValue {
|
||||||
const buf = try readAllocBytes(allocator, in_stream, size);
|
const buf = try readAllocBytes(allocator, in_stream, size);
|
||||||
return FormValue { .Block = buf };
|
return FormValue { .Block = buf };
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parseFormValueBlock(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) -> %FormValue {
|
fn parseFormValueBlock(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) %FormValue {
|
||||||
const block_len = try in_stream.readVarInt(builtin.Endian.Little, usize, size);
|
const block_len = try in_stream.readVarInt(builtin.Endian.Little, usize, size);
|
||||||
return parseFormValueBlockLen(allocator, in_stream, block_len);
|
return parseFormValueBlockLen(allocator, in_stream, block_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parseFormValueConstant(allocator: &mem.Allocator, in_stream: &io.InStream, signed: bool, size: usize) -> %FormValue {
|
fn parseFormValueConstant(allocator: &mem.Allocator, in_stream: &io.InStream, signed: bool, size: usize) %FormValue {
|
||||||
return FormValue { .Const = Constant {
|
return FormValue { .Const = Constant {
|
||||||
.signed = signed,
|
.signed = signed,
|
||||||
.payload = try readAllocBytes(allocator, in_stream, size),
|
.payload = try readAllocBytes(allocator, in_stream, size),
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parseFormValueDwarfOffsetSize(in_stream: &io.InStream, is_64: bool) -> %u64 {
|
fn parseFormValueDwarfOffsetSize(in_stream: &io.InStream, is_64: bool) %u64 {
|
||||||
return if (is_64) try in_stream.readIntLe(u64)
|
return if (is_64) try in_stream.readIntLe(u64)
|
||||||
else u64(try in_stream.readIntLe(u32)) ;
|
else u64(try in_stream.readIntLe(u32)) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parseFormValueTargetAddrSize(in_stream: &io.InStream) -> %u64 {
|
fn parseFormValueTargetAddrSize(in_stream: &io.InStream) %u64 {
|
||||||
return if (@sizeOf(usize) == 4) u64(try in_stream.readIntLe(u32))
|
return if (@sizeOf(usize) == 4) u64(try in_stream.readIntLe(u32))
|
||||||
else if (@sizeOf(usize) == 8) try in_stream.readIntLe(u64)
|
else if (@sizeOf(usize) == 8) try in_stream.readIntLe(u64)
|
||||||
else unreachable;
|
else unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parseFormValueRefLen(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) -> %FormValue {
|
fn parseFormValueRefLen(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) %FormValue {
|
||||||
const buf = try readAllocBytes(allocator, in_stream, size);
|
const buf = try readAllocBytes(allocator, in_stream, size);
|
||||||
return FormValue { .Ref = buf };
|
return FormValue { .Ref = buf };
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parseFormValueRef(allocator: &mem.Allocator, in_stream: &io.InStream, comptime T: type) -> %FormValue {
|
fn parseFormValueRef(allocator: &mem.Allocator, in_stream: &io.InStream, comptime T: type) %FormValue {
|
||||||
const block_len = try in_stream.readIntLe(T);
|
const block_len = try in_stream.readIntLe(T);
|
||||||
return parseFormValueRefLen(allocator, in_stream, block_len);
|
return parseFormValueRefLen(allocator, in_stream, block_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parseFormValue(allocator: &mem.Allocator, in_stream: &io.InStream, form_id: u64, is_64: bool) -> %FormValue {
|
fn parseFormValue(allocator: &mem.Allocator, in_stream: &io.InStream, form_id: u64, is_64: bool) %FormValue {
|
||||||
return switch (form_id) {
|
return switch (form_id) {
|
||||||
DW.FORM_addr => FormValue { .Address = try parseFormValueTargetAddrSize(in_stream) },
|
DW.FORM_addr => FormValue { .Address = try parseFormValueTargetAddrSize(in_stream) },
|
||||||
DW.FORM_block1 => parseFormValueBlock(allocator, in_stream, 1),
|
DW.FORM_block1 => parseFormValueBlock(allocator, in_stream, 1),
|
||||||
@ -656,7 +656,7 @@ fn parseFormValue(allocator: &mem.Allocator, in_stream: &io.InStream, form_id: u
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parseAbbrevTable(st: &ElfStackTrace) -> %AbbrevTable {
|
fn parseAbbrevTable(st: &ElfStackTrace) %AbbrevTable {
|
||||||
const in_file = &st.self_exe_file;
|
const in_file = &st.self_exe_file;
|
||||||
var in_file_stream = io.FileInStream.init(in_file);
|
var in_file_stream = io.FileInStream.init(in_file);
|
||||||
const in_stream = &in_file_stream.stream;
|
const in_stream = &in_file_stream.stream;
|
||||||
@ -688,7 +688,7 @@ fn parseAbbrevTable(st: &ElfStackTrace) -> %AbbrevTable {
|
|||||||
|
|
||||||
/// Gets an already existing AbbrevTable given the abbrev_offset, or if not found,
|
/// Gets an already existing AbbrevTable given the abbrev_offset, or if not found,
|
||||||
/// seeks in the stream and parses it.
|
/// seeks in the stream and parses it.
|
||||||
fn getAbbrevTable(st: &ElfStackTrace, abbrev_offset: u64) -> %&const AbbrevTable {
|
fn getAbbrevTable(st: &ElfStackTrace, abbrev_offset: u64) %&const AbbrevTable {
|
||||||
for (st.abbrev_table_list.toSlice()) |*header| {
|
for (st.abbrev_table_list.toSlice()) |*header| {
|
||||||
if (header.offset == abbrev_offset) {
|
if (header.offset == abbrev_offset) {
|
||||||
return &header.table;
|
return &header.table;
|
||||||
@ -702,7 +702,7 @@ fn getAbbrevTable(st: &ElfStackTrace, abbrev_offset: u64) -> %&const AbbrevTable
|
|||||||
return &st.abbrev_table_list.items[st.abbrev_table_list.len - 1].table;
|
return &st.abbrev_table_list.items[st.abbrev_table_list.len - 1].table;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getAbbrevTableEntry(abbrev_table: &const AbbrevTable, abbrev_code: u64) -> ?&const AbbrevTableEntry {
|
fn getAbbrevTableEntry(abbrev_table: &const AbbrevTable, abbrev_code: u64) ?&const AbbrevTableEntry {
|
||||||
for (abbrev_table.toSliceConst()) |*table_entry| {
|
for (abbrev_table.toSliceConst()) |*table_entry| {
|
||||||
if (table_entry.abbrev_code == abbrev_code)
|
if (table_entry.abbrev_code == abbrev_code)
|
||||||
return table_entry;
|
return table_entry;
|
||||||
@ -710,7 +710,7 @@ fn getAbbrevTableEntry(abbrev_table: &const AbbrevTable, abbrev_code: u64) -> ?&
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parseDie(st: &ElfStackTrace, abbrev_table: &const AbbrevTable, is_64: bool) -> %Die {
|
fn parseDie(st: &ElfStackTrace, abbrev_table: &const AbbrevTable, is_64: bool) %Die {
|
||||||
const in_file = &st.self_exe_file;
|
const in_file = &st.self_exe_file;
|
||||||
var in_file_stream = io.FileInStream.init(in_file);
|
var in_file_stream = io.FileInStream.init(in_file);
|
||||||
const in_stream = &in_file_stream.stream;
|
const in_stream = &in_file_stream.stream;
|
||||||
@ -732,7 +732,7 @@ fn parseDie(st: &ElfStackTrace, abbrev_table: &const AbbrevTable, is_64: bool) -
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, target_address: usize) -> %LineInfo {
|
fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, target_address: usize) %LineInfo {
|
||||||
const compile_unit_cwd = try compile_unit.die.getAttrString(st, DW.AT_comp_dir);
|
const compile_unit_cwd = try compile_unit.die.getAttrString(st, DW.AT_comp_dir);
|
||||||
|
|
||||||
const in_file = &st.self_exe_file;
|
const in_file = &st.self_exe_file;
|
||||||
@ -910,7 +910,7 @@ fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, targe
|
|||||||
return error.MissingDebugInfo;
|
return error.MissingDebugInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scanAllCompileUnits(st: &ElfStackTrace) -> %void {
|
fn scanAllCompileUnits(st: &ElfStackTrace) %void {
|
||||||
const debug_info_end = st.debug_info.offset + st.debug_info.size;
|
const debug_info_end = st.debug_info.offset + st.debug_info.size;
|
||||||
var this_unit_offset = st.debug_info.offset;
|
var this_unit_offset = st.debug_info.offset;
|
||||||
var cu_index: usize = 0;
|
var cu_index: usize = 0;
|
||||||
@ -986,7 +986,7 @@ fn scanAllCompileUnits(st: &ElfStackTrace) -> %void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn findCompileUnit(st: &ElfStackTrace, target_address: u64) -> %&const CompileUnit {
|
fn findCompileUnit(st: &ElfStackTrace, target_address: u64) %&const CompileUnit {
|
||||||
var in_file_stream = io.FileInStream.init(&st.self_exe_file);
|
var in_file_stream = io.FileInStream.init(&st.self_exe_file);
|
||||||
const in_stream = &in_file_stream.stream;
|
const in_stream = &in_file_stream.stream;
|
||||||
for (st.compile_unit_list.toSlice()) |*compile_unit| {
|
for (st.compile_unit_list.toSlice()) |*compile_unit| {
|
||||||
@ -1022,7 +1022,7 @@ fn findCompileUnit(st: &ElfStackTrace, target_address: u64) -> %&const CompileUn
|
|||||||
return error.MissingDebugInfo;
|
return error.MissingDebugInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn readInitialLength(in_stream: &io.InStream, is_64: &bool) -> %u64 {
|
fn readInitialLength(in_stream: &io.InStream, is_64: &bool) %u64 {
|
||||||
const first_32_bits = try in_stream.readIntLe(u32);
|
const first_32_bits = try in_stream.readIntLe(u32);
|
||||||
*is_64 = (first_32_bits == 0xffffffff);
|
*is_64 = (first_32_bits == 0xffffffff);
|
||||||
if (*is_64) {
|
if (*is_64) {
|
||||||
@ -1033,7 +1033,7 @@ fn readInitialLength(in_stream: &io.InStream, is_64: &bool) -> %u64 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn readULeb128(in_stream: &io.InStream) -> %u64 {
|
fn readULeb128(in_stream: &io.InStream) %u64 {
|
||||||
var result: u64 = 0;
|
var result: u64 = 0;
|
||||||
var shift: usize = 0;
|
var shift: usize = 0;
|
||||||
|
|
||||||
@ -1054,7 +1054,7 @@ fn readULeb128(in_stream: &io.InStream) -> %u64 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn readILeb128(in_stream: &io.InStream) -> %i64 {
|
fn readILeb128(in_stream: &io.InStream) %i64 {
|
||||||
var result: i64 = 0;
|
var result: i64 = 0;
|
||||||
var shift: usize = 0;
|
var shift: usize = 0;
|
||||||
|
|
||||||
|
10
std/elf.zig
10
std/elf.zig
@ -81,14 +81,14 @@ pub const Elf = struct {
|
|||||||
prealloc_file: io.File,
|
prealloc_file: io.File,
|
||||||
|
|
||||||
/// Call close when done.
|
/// Call close when done.
|
||||||
pub fn openPath(elf: &Elf, allocator: &mem.Allocator, path: []const u8) -> %void {
|
pub fn openPath(elf: &Elf, allocator: &mem.Allocator, path: []const u8) %void {
|
||||||
try elf.prealloc_file.open(path);
|
try elf.prealloc_file.open(path);
|
||||||
try elf.openFile(allocator, &elf.prealloc_file);
|
try elf.openFile(allocator, &elf.prealloc_file);
|
||||||
elf.auto_close_stream = true;
|
elf.auto_close_stream = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Call close when done.
|
/// Call close when done.
|
||||||
pub fn openFile(elf: &Elf, allocator: &mem.Allocator, file: &io.File) -> %void {
|
pub fn openFile(elf: &Elf, allocator: &mem.Allocator, file: &io.File) %void {
|
||||||
elf.allocator = allocator;
|
elf.allocator = allocator;
|
||||||
elf.in_file = file;
|
elf.in_file = file;
|
||||||
elf.auto_close_stream = false;
|
elf.auto_close_stream = false;
|
||||||
@ -232,14 +232,14 @@ pub const Elf = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn close(elf: &Elf) {
|
pub fn close(elf: &Elf) void {
|
||||||
elf.allocator.free(elf.section_headers);
|
elf.allocator.free(elf.section_headers);
|
||||||
|
|
||||||
if (elf.auto_close_stream)
|
if (elf.auto_close_stream)
|
||||||
elf.in_file.close();
|
elf.in_file.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn findSection(elf: &Elf, name: []const u8) -> %?&SectionHeader {
|
pub fn findSection(elf: &Elf, name: []const u8) %?&SectionHeader {
|
||||||
var file_stream = io.FileInStream.init(elf.in_file);
|
var file_stream = io.FileInStream.init(elf.in_file);
|
||||||
const in = &file_stream.stream;
|
const in = &file_stream.stream;
|
||||||
|
|
||||||
@ -263,7 +263,7 @@ pub const Elf = struct {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn seekToSection(elf: &Elf, elf_section: &SectionHeader) -> %void {
|
pub fn seekToSection(elf: &Elf, elf_section: &SectionHeader) %void {
|
||||||
try elf.in_file.seekTo(elf_section.offset);
|
try elf.in_file.seekTo(elf_section.offset);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1,19 +1,19 @@
|
|||||||
const mem = @import("mem.zig");
|
const mem = @import("mem.zig");
|
||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
|
|
||||||
pub fn swapIfLe(comptime T: type, x: T) -> T {
|
pub fn swapIfLe(comptime T: type, x: T) T {
|
||||||
return swapIf(builtin.Endian.Little, T, x);
|
return swapIf(builtin.Endian.Little, T, x);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn swapIfBe(comptime T: type, x: T) -> T {
|
pub fn swapIfBe(comptime T: type, x: T) T {
|
||||||
return swapIf(builtin.Endian.Big, T, x);
|
return swapIf(builtin.Endian.Big, T, x);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn swapIf(endian: builtin.Endian, comptime T: type, x: T) -> T {
|
pub fn swapIf(endian: builtin.Endian, comptime T: type, x: T) T {
|
||||||
return if (builtin.endian == endian) swap(T, x) else x;
|
return if (builtin.endian == endian) swap(T, x) else x;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn swap(comptime T: type, x: T) -> T {
|
pub fn swap(comptime T: type, x: T) T {
|
||||||
var buf: [@sizeOf(T)]u8 = undefined;
|
var buf: [@sizeOf(T)]u8 = undefined;
|
||||||
mem.writeInt(buf[0..], x, builtin.Endian.Little);
|
mem.writeInt(buf[0..], x, builtin.Endian.Little);
|
||||||
return mem.readInt(buf, T, builtin.Endian.Big);
|
return mem.readInt(buf, T, builtin.Endian.Big);
|
||||||
|
@ -438,7 +438,7 @@ const Slab = struct {
|
|||||||
exp: i32,
|
exp: i32,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn slab(str: []const u8, exp: i32) -> Slab {
|
fn slab(str: []const u8, exp: i32) Slab {
|
||||||
return Slab {
|
return Slab {
|
||||||
.str = str,
|
.str = str,
|
||||||
.exp = exp,
|
.exp = exp,
|
||||||
|
@ -13,7 +13,7 @@ pub const FloatDecimal = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// Corrected Errol3 double to ASCII conversion.
|
/// Corrected Errol3 double to ASCII conversion.
|
||||||
pub fn errol3(value: f64, buffer: []u8) -> FloatDecimal {
|
pub fn errol3(value: f64, buffer: []u8) FloatDecimal {
|
||||||
const bits = @bitCast(u64, value);
|
const bits = @bitCast(u64, value);
|
||||||
const i = tableLowerBound(bits);
|
const i = tableLowerBound(bits);
|
||||||
if (i < enum3.len and enum3[i] == bits) {
|
if (i < enum3.len and enum3[i] == bits) {
|
||||||
@ -30,7 +30,7 @@ pub fn errol3(value: f64, buffer: []u8) -> FloatDecimal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Uncorrected Errol3 double to ASCII conversion.
|
/// Uncorrected Errol3 double to ASCII conversion.
|
||||||
fn errol3u(val: f64, buffer: []u8) -> FloatDecimal {
|
fn errol3u(val: f64, buffer: []u8) FloatDecimal {
|
||||||
// check if in integer or fixed range
|
// check if in integer or fixed range
|
||||||
|
|
||||||
if (val > 9.007199254740992e15 and val < 3.40282366920938e+38) {
|
if (val > 9.007199254740992e15 and val < 3.40282366920938e+38) {
|
||||||
@ -133,7 +133,7 @@ fn errol3u(val: f64, buffer: []u8) -> FloatDecimal {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tableLowerBound(k: u64) -> usize {
|
fn tableLowerBound(k: u64) usize {
|
||||||
var i = enum3.len;
|
var i = enum3.len;
|
||||||
var j: usize = 0;
|
var j: usize = 0;
|
||||||
|
|
||||||
@ -153,7 +153,7 @@ fn tableLowerBound(k: u64) -> usize {
|
|||||||
/// @in: The HP number.
|
/// @in: The HP number.
|
||||||
/// @val: The double.
|
/// @val: The double.
|
||||||
/// &returns: The HP number.
|
/// &returns: The HP number.
|
||||||
fn hpProd(in: &const HP, val: f64) -> HP {
|
fn hpProd(in: &const HP, val: f64) HP {
|
||||||
var hi: f64 = undefined;
|
var hi: f64 = undefined;
|
||||||
var lo: f64 = undefined;
|
var lo: f64 = undefined;
|
||||||
split(in.val, &hi, &lo);
|
split(in.val, &hi, &lo);
|
||||||
@ -175,12 +175,12 @@ fn hpProd(in: &const HP, val: f64) -> HP {
|
|||||||
/// @val: The double.
|
/// @val: The double.
|
||||||
/// @hi: The high bits.
|
/// @hi: The high bits.
|
||||||
/// @lo: The low bits.
|
/// @lo: The low bits.
|
||||||
fn split(val: f64, hi: &f64, lo: &f64) {
|
fn split(val: f64, hi: &f64, lo: &f64) void {
|
||||||
*hi = gethi(val);
|
*hi = gethi(val);
|
||||||
*lo = val - *hi;
|
*lo = val - *hi;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gethi(in: f64) -> f64 {
|
fn gethi(in: f64) f64 {
|
||||||
const bits = @bitCast(u64, in);
|
const bits = @bitCast(u64, in);
|
||||||
const new_bits = bits & 0xFFFFFFFFF8000000;
|
const new_bits = bits & 0xFFFFFFFFF8000000;
|
||||||
return @bitCast(f64, new_bits);
|
return @bitCast(f64, new_bits);
|
||||||
@ -188,7 +188,7 @@ fn gethi(in: f64) -> f64 {
|
|||||||
|
|
||||||
/// Normalize the number by factoring in the error.
|
/// Normalize the number by factoring in the error.
|
||||||
/// @hp: The float pair.
|
/// @hp: The float pair.
|
||||||
fn hpNormalize(hp: &HP) {
|
fn hpNormalize(hp: &HP) void {
|
||||||
const val = hp.val;
|
const val = hp.val;
|
||||||
|
|
||||||
hp.val += hp.off;
|
hp.val += hp.off;
|
||||||
@ -197,7 +197,7 @@ fn hpNormalize(hp: &HP) {
|
|||||||
|
|
||||||
/// Divide the high-precision number by ten.
|
/// Divide the high-precision number by ten.
|
||||||
/// @hp: The high-precision number
|
/// @hp: The high-precision number
|
||||||
fn hpDiv10(hp: &HP) {
|
fn hpDiv10(hp: &HP) void {
|
||||||
var val = hp.val;
|
var val = hp.val;
|
||||||
|
|
||||||
hp.val /= 10.0;
|
hp.val /= 10.0;
|
||||||
@ -213,7 +213,7 @@ fn hpDiv10(hp: &HP) {
|
|||||||
|
|
||||||
/// Multiply the high-precision number by ten.
|
/// Multiply the high-precision number by ten.
|
||||||
/// @hp: The high-precision number
|
/// @hp: The high-precision number
|
||||||
fn hpMul10(hp: &HP) {
|
fn hpMul10(hp: &HP) void {
|
||||||
const val = hp.val;
|
const val = hp.val;
|
||||||
|
|
||||||
hp.val *= 10.0;
|
hp.val *= 10.0;
|
||||||
@ -233,7 +233,7 @@ fn hpMul10(hp: &HP) {
|
|||||||
/// @val: The val.
|
/// @val: The val.
|
||||||
/// @buf: The output buffer.
|
/// @buf: The output buffer.
|
||||||
/// &return: The exponent.
|
/// &return: The exponent.
|
||||||
fn errolInt(val: f64, buffer: []u8) -> FloatDecimal {
|
fn errolInt(val: f64, buffer: []u8) FloatDecimal {
|
||||||
const pow19 = u128(1e19);
|
const pow19 = u128(1e19);
|
||||||
|
|
||||||
assert((val > 9.007199254740992e15) and val < (3.40282366920938e38));
|
assert((val > 9.007199254740992e15) and val < (3.40282366920938e38));
|
||||||
@ -291,7 +291,7 @@ fn errolInt(val: f64, buffer: []u8) -> FloatDecimal {
|
|||||||
/// @val: The val.
|
/// @val: The val.
|
||||||
/// @buf: The output buffer.
|
/// @buf: The output buffer.
|
||||||
/// &return: The exponent.
|
/// &return: The exponent.
|
||||||
fn errolFixed(val: f64, buffer: []u8) -> FloatDecimal {
|
fn errolFixed(val: f64, buffer: []u8) FloatDecimal {
|
||||||
assert((val >= 16.0) and (val < 9.007199254740992e15));
|
assert((val >= 16.0) and (val < 9.007199254740992e15));
|
||||||
|
|
||||||
const u = u64(val);
|
const u = u64(val);
|
||||||
@ -347,11 +347,11 @@ fn errolFixed(val: f64, buffer: []u8) -> FloatDecimal {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fpnext(val: f64) -> f64 {
|
fn fpnext(val: f64) f64 {
|
||||||
return @bitCast(f64, @bitCast(u64, val) +% 1);
|
return @bitCast(f64, @bitCast(u64, val) +% 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fpprev(val: f64) -> f64 {
|
fn fpprev(val: f64) f64 {
|
||||||
return @bitCast(f64, @bitCast(u64, val) -% 1);
|
return @bitCast(f64, @bitCast(u64, val) -% 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -373,7 +373,7 @@ pub const c_digits_lut = []u8 {
|
|||||||
'9', '8', '9', '9',
|
'9', '8', '9', '9',
|
||||||
};
|
};
|
||||||
|
|
||||||
fn u64toa(value_param: u64, buffer: []u8) -> usize {
|
fn u64toa(value_param: u64, buffer: []u8) usize {
|
||||||
var value = value_param;
|
var value = value_param;
|
||||||
const kTen8: u64 = 100000000;
|
const kTen8: u64 = 100000000;
|
||||||
const kTen9: u64 = kTen8 * 10;
|
const kTen9: u64 = kTen8 * 10;
|
||||||
@ -606,7 +606,7 @@ fn u64toa(value_param: u64, buffer: []u8) -> usize {
|
|||||||
return buf_index;
|
return buf_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fpeint(from: f64) -> u128 {
|
fn fpeint(from: f64) u128 {
|
||||||
const bits = @bitCast(u64, from);
|
const bits = @bitCast(u64, from);
|
||||||
assert((bits & ((1 << 52) - 1)) == 0);
|
assert((bits & ((1 << 52) - 1)) == 0);
|
||||||
|
|
||||||
@ -621,7 +621,7 @@ fn fpeint(from: f64) -> u128 {
|
|||||||
/// @a: Integer a.
|
/// @a: Integer a.
|
||||||
/// @b: Integer b.
|
/// @b: Integer b.
|
||||||
/// &returns: An index within [0, 19).
|
/// &returns: An index within [0, 19).
|
||||||
fn mismatch10(a: u64, b: u64) -> i32 {
|
fn mismatch10(a: u64, b: u64) i32 {
|
||||||
const pow10 = 10000000000;
|
const pow10 = 10000000000;
|
||||||
const af = a / pow10;
|
const af = a / pow10;
|
||||||
const bf = b / pow10;
|
const bf = b / pow10;
|
||||||
|
@ -24,8 +24,8 @@ const State = enum { // TODO put inside format function and make sure the name a
|
|||||||
/// Renders fmt string with args, calling output with slices of bytes.
|
/// Renders fmt string with args, calling output with slices of bytes.
|
||||||
/// If `output` returns an error, the error is returned from `format` and
|
/// If `output` returns an error, the error is returned from `format` and
|
||||||
/// `output` is not called again.
|
/// `output` is not called again.
|
||||||
pub fn format(context: var, output: fn(@typeOf(context), []const u8)->%void,
|
pub fn format(context: var, output: fn(@typeOf(context), []const u8)%void,
|
||||||
comptime fmt: []const u8, args: ...) -> %void
|
comptime fmt: []const u8, args: ...) %void
|
||||||
{
|
{
|
||||||
comptime var start_index = 0;
|
comptime var start_index = 0;
|
||||||
comptime var state = State.Start;
|
comptime var state = State.Start;
|
||||||
@ -191,7 +191,7 @@ pub fn format(context: var, output: fn(@typeOf(context), []const u8)->%void,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn formatValue(value: var, context: var, output: fn(@typeOf(context), []const u8)->%void) -> %void {
|
pub fn formatValue(value: var, context: var, output: fn(@typeOf(context), []const u8)%void) %void {
|
||||||
const T = @typeOf(value);
|
const T = @typeOf(value);
|
||||||
switch (@typeId(T)) {
|
switch (@typeId(T)) {
|
||||||
builtin.TypeId.Int => {
|
builtin.TypeId.Int => {
|
||||||
@ -240,12 +240,12 @@ pub fn formatValue(value: var, context: var, output: fn(@typeOf(context), []cons
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn formatAsciiChar(c: u8, context: var, output: fn(@typeOf(context), []const u8)->%void) -> %void {
|
pub fn formatAsciiChar(c: u8, context: var, output: fn(@typeOf(context), []const u8)%void) %void {
|
||||||
return output(context, (&c)[0..1]);
|
return output(context, (&c)[0..1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn formatBuf(buf: []const u8, width: usize,
|
pub fn formatBuf(buf: []const u8, width: usize,
|
||||||
context: var, output: fn(@typeOf(context), []const u8)->%void) -> %void
|
context: var, output: fn(@typeOf(context), []const u8)%void) %void
|
||||||
{
|
{
|
||||||
try output(context, buf);
|
try output(context, buf);
|
||||||
|
|
||||||
@ -256,7 +256,7 @@ pub fn formatBuf(buf: []const u8, width: usize,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn formatFloat(value: var, context: var, output: fn(@typeOf(context), []const u8)->%void) -> %void {
|
pub fn formatFloat(value: var, context: var, output: fn(@typeOf(context), []const u8)%void) %void {
|
||||||
var x = f64(value);
|
var x = f64(value);
|
||||||
|
|
||||||
// Errol doesn't handle these special cases.
|
// Errol doesn't handle these special cases.
|
||||||
@ -294,7 +294,7 @@ pub fn formatFloat(value: var, context: var, output: fn(@typeOf(context), []cons
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn formatFloatDecimal(value: var, precision: usize, context: var, output: fn(@typeOf(context), []const u8)->%void) -> %void {
|
pub fn formatFloatDecimal(value: var, precision: usize, context: var, output: fn(@typeOf(context), []const u8)%void) %void {
|
||||||
var x = f64(value);
|
var x = f64(value);
|
||||||
|
|
||||||
// Errol doesn't handle these special cases.
|
// Errol doesn't handle these special cases.
|
||||||
@ -336,7 +336,7 @@ pub fn formatFloatDecimal(value: var, precision: usize, context: var, output: fn
|
|||||||
|
|
||||||
|
|
||||||
pub fn formatInt(value: var, base: u8, uppercase: bool, width: usize,
|
pub fn formatInt(value: var, base: u8, uppercase: bool, width: usize,
|
||||||
context: var, output: fn(@typeOf(context), []const u8)->%void) -> %void
|
context: var, output: fn(@typeOf(context), []const u8)%void) %void
|
||||||
{
|
{
|
||||||
if (@typeOf(value).is_signed) {
|
if (@typeOf(value).is_signed) {
|
||||||
return formatIntSigned(value, base, uppercase, width, context, output);
|
return formatIntSigned(value, base, uppercase, width, context, output);
|
||||||
@ -346,7 +346,7 @@ pub fn formatInt(value: var, base: u8, uppercase: bool, width: usize,
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn formatIntSigned(value: var, base: u8, uppercase: bool, width: usize,
|
fn formatIntSigned(value: var, base: u8, uppercase: bool, width: usize,
|
||||||
context: var, output: fn(@typeOf(context), []const u8)->%void) -> %void
|
context: var, output: fn(@typeOf(context), []const u8)%void) %void
|
||||||
{
|
{
|
||||||
const uint = @IntType(false, @typeOf(value).bit_count);
|
const uint = @IntType(false, @typeOf(value).bit_count);
|
||||||
if (value < 0) {
|
if (value < 0) {
|
||||||
@ -367,7 +367,7 @@ fn formatIntSigned(value: var, base: u8, uppercase: bool, width: usize,
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn formatIntUnsigned(value: var, base: u8, uppercase: bool, width: usize,
|
fn formatIntUnsigned(value: var, base: u8, uppercase: bool, width: usize,
|
||||||
context: var, output: fn(@typeOf(context), []const u8)->%void) -> %void
|
context: var, output: fn(@typeOf(context), []const u8)%void) %void
|
||||||
{
|
{
|
||||||
// max_int_digits accounts for the minus sign. when printing an unsigned
|
// max_int_digits accounts for the minus sign. when printing an unsigned
|
||||||
// number we don't need to do that.
|
// number we don't need to do that.
|
||||||
@ -405,7 +405,7 @@ fn formatIntUnsigned(value: var, base: u8, uppercase: bool, width: usize,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn formatIntBuf(out_buf: []u8, value: var, base: u8, uppercase: bool, width: usize) -> usize {
|
pub fn formatIntBuf(out_buf: []u8, value: var, base: u8, uppercase: bool, width: usize) usize {
|
||||||
var context = FormatIntBuf {
|
var context = FormatIntBuf {
|
||||||
.out_buf = out_buf,
|
.out_buf = out_buf,
|
||||||
.index = 0,
|
.index = 0,
|
||||||
@ -417,12 +417,12 @@ const FormatIntBuf = struct {
|
|||||||
out_buf: []u8,
|
out_buf: []u8,
|
||||||
index: usize,
|
index: usize,
|
||||||
};
|
};
|
||||||
fn formatIntCallback(context: &FormatIntBuf, bytes: []const u8) -> %void {
|
fn formatIntCallback(context: &FormatIntBuf, bytes: []const u8) %void {
|
||||||
mem.copy(u8, context.out_buf[context.index..], bytes);
|
mem.copy(u8, context.out_buf[context.index..], bytes);
|
||||||
context.index += bytes.len;
|
context.index += bytes.len;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parseInt(comptime T: type, buf: []const u8, radix: u8) -> %T {
|
pub fn parseInt(comptime T: type, buf: []const u8, radix: u8) %T {
|
||||||
if (!T.is_signed)
|
if (!T.is_signed)
|
||||||
return parseUnsigned(T, buf, radix);
|
return parseUnsigned(T, buf, radix);
|
||||||
if (buf.len == 0)
|
if (buf.len == 0)
|
||||||
@ -446,7 +446,7 @@ test "fmt.parseInt" {
|
|||||||
assert(if (parseInt(u8, "256", 10)) |_| false else |err| err == error.Overflow);
|
assert(if (parseInt(u8, "256", 10)) |_| false else |err| err == error.Overflow);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parseUnsigned(comptime T: type, buf: []const u8, radix: u8) -> %T {
|
pub fn parseUnsigned(comptime T: type, buf: []const u8, radix: u8) %T {
|
||||||
var x: T = 0;
|
var x: T = 0;
|
||||||
|
|
||||||
for (buf) |c| {
|
for (buf) |c| {
|
||||||
@ -459,7 +459,7 @@ pub fn parseUnsigned(comptime T: type, buf: []const u8, radix: u8) -> %T {
|
|||||||
}
|
}
|
||||||
|
|
||||||
error InvalidChar;
|
error InvalidChar;
|
||||||
fn charToDigit(c: u8, radix: u8) -> %u8 {
|
fn charToDigit(c: u8, radix: u8) %u8 {
|
||||||
const value = switch (c) {
|
const value = switch (c) {
|
||||||
'0' ... '9' => c - '0',
|
'0' ... '9' => c - '0',
|
||||||
'A' ... 'Z' => c - 'A' + 10,
|
'A' ... 'Z' => c - 'A' + 10,
|
||||||
@ -473,7 +473,7 @@ fn charToDigit(c: u8, radix: u8) -> %u8 {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn digitToChar(digit: u8, uppercase: bool) -> u8 {
|
fn digitToChar(digit: u8, uppercase: bool) u8 {
|
||||||
return switch (digit) {
|
return switch (digit) {
|
||||||
0 ... 9 => digit + '0',
|
0 ... 9 => digit + '0',
|
||||||
10 ... 35 => digit + ((if (uppercase) u8('A') else u8('a')) - 10),
|
10 ... 35 => digit + ((if (uppercase) u8('A') else u8('a')) - 10),
|
||||||
@ -486,19 +486,19 @@ const BufPrintContext = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
error BufferTooSmall;
|
error BufferTooSmall;
|
||||||
fn bufPrintWrite(context: &BufPrintContext, bytes: []const u8) -> %void {
|
fn bufPrintWrite(context: &BufPrintContext, bytes: []const u8) %void {
|
||||||
if (context.remaining.len < bytes.len) return error.BufferTooSmall;
|
if (context.remaining.len < bytes.len) return error.BufferTooSmall;
|
||||||
mem.copy(u8, context.remaining, bytes);
|
mem.copy(u8, context.remaining, bytes);
|
||||||
context.remaining = context.remaining[bytes.len..];
|
context.remaining = context.remaining[bytes.len..];
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: ...) -> %[]u8 {
|
pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: ...) %[]u8 {
|
||||||
var context = BufPrintContext { .remaining = buf, };
|
var context = BufPrintContext { .remaining = buf, };
|
||||||
try format(&context, bufPrintWrite, fmt, args);
|
try format(&context, bufPrintWrite, fmt, args);
|
||||||
return buf[0..buf.len - context.remaining.len];
|
return buf[0..buf.len - context.remaining.len];
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn allocPrint(allocator: &mem.Allocator, comptime fmt: []const u8, args: ...) -> %[]u8 {
|
pub fn allocPrint(allocator: &mem.Allocator, comptime fmt: []const u8, args: ...) %[]u8 {
|
||||||
var size: usize = 0;
|
var size: usize = 0;
|
||||||
// Cannot fail because `countSize` cannot fail.
|
// Cannot fail because `countSize` cannot fail.
|
||||||
format(&size, countSize, fmt, args) catch unreachable;
|
format(&size, countSize, fmt, args) catch unreachable;
|
||||||
@ -506,7 +506,7 @@ pub fn allocPrint(allocator: &mem.Allocator, comptime fmt: []const u8, args: ...
|
|||||||
return bufPrint(buf, fmt, args);
|
return bufPrint(buf, fmt, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn countSize(size: &usize, bytes: []const u8) -> %void {
|
fn countSize(size: &usize, bytes: []const u8) %void {
|
||||||
*size += bytes.len;
|
*size += bytes.len;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -528,7 +528,7 @@ test "buf print int" {
|
|||||||
assert(mem.eql(u8, bufPrintIntToSlice(buf, i32(-42), 10, false, 3), "-42"));
|
assert(mem.eql(u8, bufPrintIntToSlice(buf, i32(-42), 10, false, 3), "-42"));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bufPrintIntToSlice(buf: []u8, value: var, base: u8, uppercase: bool, width: usize) -> []u8 {
|
fn bufPrintIntToSlice(buf: []u8, value: var, base: u8, uppercase: bool, width: usize) []u8 {
|
||||||
return buf[0..formatIntBuf(buf, value, base, uppercase, width)];
|
return buf[0..formatIntBuf(buf, value, base, uppercase, width)];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -644,7 +644,7 @@ test "fmt.format" {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn trim(buf: []const u8) -> []const u8 {
|
pub fn trim(buf: []const u8) []const u8 {
|
||||||
var start: usize = 0;
|
var start: usize = 0;
|
||||||
while (start < buf.len and isWhiteSpace(buf[start])) : (start += 1) { }
|
while (start < buf.len and isWhiteSpace(buf[start])) : (start += 1) { }
|
||||||
|
|
||||||
@ -671,7 +671,7 @@ test "fmt.trim" {
|
|||||||
assert(mem.eql(u8, "abc", trim("abc ")));
|
assert(mem.eql(u8, "abc", trim("abc ")));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn isWhiteSpace(byte: u8) -> bool {
|
pub fn isWhiteSpace(byte: u8) bool {
|
||||||
return switch (byte) {
|
return switch (byte) {
|
||||||
' ', '\t', '\n', '\r' => true,
|
' ', '\t', '\n', '\r' => true,
|
||||||
else => false,
|
else => false,
|
||||||
|
@ -10,8 +10,8 @@ const want_modification_safety = builtin.mode != builtin.Mode.ReleaseFast;
|
|||||||
const debug_u32 = if (want_modification_safety) u32 else void;
|
const debug_u32 = if (want_modification_safety) u32 else void;
|
||||||
|
|
||||||
pub fn HashMap(comptime K: type, comptime V: type,
|
pub fn HashMap(comptime K: type, comptime V: type,
|
||||||
comptime hash: fn(key: K)->u32,
|
comptime hash: fn(key: K)u32,
|
||||||
comptime eql: fn(a: K, b: K)->bool) -> type
|
comptime eql: fn(a: K, b: K)bool) type
|
||||||
{
|
{
|
||||||
return struct {
|
return struct {
|
||||||
entries: []Entry,
|
entries: []Entry,
|
||||||
@ -39,7 +39,7 @@ pub fn HashMap(comptime K: type, comptime V: type,
|
|||||||
// used to detect concurrent modification
|
// used to detect concurrent modification
|
||||||
initial_modification_count: debug_u32,
|
initial_modification_count: debug_u32,
|
||||||
|
|
||||||
pub fn next(it: &Iterator) -> ?&Entry {
|
pub fn next(it: &Iterator) ?&Entry {
|
||||||
if (want_modification_safety) {
|
if (want_modification_safety) {
|
||||||
assert(it.initial_modification_count == it.hm.modification_count); // concurrent modification
|
assert(it.initial_modification_count == it.hm.modification_count); // concurrent modification
|
||||||
}
|
}
|
||||||
@ -56,7 +56,7 @@ pub fn HashMap(comptime K: type, comptime V: type,
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn init(allocator: &Allocator) -> Self {
|
pub fn init(allocator: &Allocator) Self {
|
||||||
return Self {
|
return Self {
|
||||||
.entries = []Entry{},
|
.entries = []Entry{},
|
||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
@ -66,11 +66,11 @@ pub fn HashMap(comptime K: type, comptime V: type,
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(hm: &Self) {
|
pub fn deinit(hm: &Self) void {
|
||||||
hm.allocator.free(hm.entries);
|
hm.allocator.free(hm.entries);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clear(hm: &Self) {
|
pub fn clear(hm: &Self) void {
|
||||||
for (hm.entries) |*entry| {
|
for (hm.entries) |*entry| {
|
||||||
entry.used = false;
|
entry.used = false;
|
||||||
}
|
}
|
||||||
@ -80,7 +80,7 @@ pub fn HashMap(comptime K: type, comptime V: type,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the value that was already there.
|
/// Returns the value that was already there.
|
||||||
pub fn put(hm: &Self, key: K, value: &const V) -> %?V {
|
pub fn put(hm: &Self, key: K, value: &const V) %?V {
|
||||||
if (hm.entries.len == 0) {
|
if (hm.entries.len == 0) {
|
||||||
try hm.initCapacity(16);
|
try hm.initCapacity(16);
|
||||||
}
|
}
|
||||||
@ -102,18 +102,18 @@ pub fn HashMap(comptime K: type, comptime V: type,
|
|||||||
return hm.internalPut(key, value);
|
return hm.internalPut(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get(hm: &Self, key: K) -> ?&Entry {
|
pub fn get(hm: &Self, key: K) ?&Entry {
|
||||||
if (hm.entries.len == 0) {
|
if (hm.entries.len == 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return hm.internalGet(key);
|
return hm.internalGet(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn contains(hm: &Self, key: K) -> bool {
|
pub fn contains(hm: &Self, key: K) bool {
|
||||||
return hm.get(key) != null;
|
return hm.get(key) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove(hm: &Self, key: K) -> ?&Entry {
|
pub fn remove(hm: &Self, key: K) ?&Entry {
|
||||||
hm.incrementModificationCount();
|
hm.incrementModificationCount();
|
||||||
const start_index = hm.keyToIndex(key);
|
const start_index = hm.keyToIndex(key);
|
||||||
{var roll_over: usize = 0; while (roll_over <= hm.max_distance_from_start_index) : (roll_over += 1) {
|
{var roll_over: usize = 0; while (roll_over <= hm.max_distance_from_start_index) : (roll_over += 1) {
|
||||||
@ -142,7 +142,7 @@ pub fn HashMap(comptime K: type, comptime V: type,
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iterator(hm: &const Self) -> Iterator {
|
pub fn iterator(hm: &const Self) Iterator {
|
||||||
return Iterator {
|
return Iterator {
|
||||||
.hm = hm,
|
.hm = hm,
|
||||||
.count = 0,
|
.count = 0,
|
||||||
@ -151,7 +151,7 @@ pub fn HashMap(comptime K: type, comptime V: type,
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn initCapacity(hm: &Self, capacity: usize) -> %void {
|
fn initCapacity(hm: &Self, capacity: usize) %void {
|
||||||
hm.entries = try hm.allocator.alloc(Entry, capacity);
|
hm.entries = try hm.allocator.alloc(Entry, capacity);
|
||||||
hm.size = 0;
|
hm.size = 0;
|
||||||
hm.max_distance_from_start_index = 0;
|
hm.max_distance_from_start_index = 0;
|
||||||
@ -160,14 +160,14 @@ pub fn HashMap(comptime K: type, comptime V: type,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn incrementModificationCount(hm: &Self) {
|
fn incrementModificationCount(hm: &Self) void {
|
||||||
if (want_modification_safety) {
|
if (want_modification_safety) {
|
||||||
hm.modification_count +%= 1;
|
hm.modification_count +%= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the value that was already there.
|
/// Returns the value that was already there.
|
||||||
fn internalPut(hm: &Self, orig_key: K, orig_value: &const V) -> ?V {
|
fn internalPut(hm: &Self, orig_key: K, orig_value: &const V) ?V {
|
||||||
var key = orig_key;
|
var key = orig_key;
|
||||||
var value = *orig_value;
|
var value = *orig_value;
|
||||||
const start_index = hm.keyToIndex(key);
|
const start_index = hm.keyToIndex(key);
|
||||||
@ -217,7 +217,7 @@ pub fn HashMap(comptime K: type, comptime V: type,
|
|||||||
unreachable; // put into a full map
|
unreachable; // put into a full map
|
||||||
}
|
}
|
||||||
|
|
||||||
fn internalGet(hm: &Self, key: K) -> ?&Entry {
|
fn internalGet(hm: &Self, key: K) ?&Entry {
|
||||||
const start_index = hm.keyToIndex(key);
|
const start_index = hm.keyToIndex(key);
|
||||||
{var roll_over: usize = 0; while (roll_over <= hm.max_distance_from_start_index) : (roll_over += 1) {
|
{var roll_over: usize = 0; while (roll_over <= hm.max_distance_from_start_index) : (roll_over += 1) {
|
||||||
const index = (start_index + roll_over) % hm.entries.len;
|
const index = (start_index + roll_over) % hm.entries.len;
|
||||||
@ -229,7 +229,7 @@ pub fn HashMap(comptime K: type, comptime V: type,
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn keyToIndex(hm: &Self, key: K) -> usize {
|
fn keyToIndex(hm: &Self, key: K) usize {
|
||||||
return usize(hash(key)) % hm.entries.len;
|
return usize(hash(key)) % hm.entries.len;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -254,10 +254,10 @@ test "basicHashMapTest" {
|
|||||||
assert(map.get(2) == null);
|
assert(map.get(2) == null);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hash_i32(x: i32) -> u32 {
|
fn hash_i32(x: i32) u32 {
|
||||||
return @bitCast(u32, x);
|
return @bitCast(u32, x);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eql_i32(a: i32, b: i32) -> bool {
|
fn eql_i32(a: i32, b: i32) bool {
|
||||||
return a == b;
|
return a == b;
|
||||||
}
|
}
|
||||||
|
20
std/heap.zig
20
std/heap.zig
@ -18,14 +18,14 @@ var c_allocator_state = Allocator {
|
|||||||
.freeFn = cFree,
|
.freeFn = cFree,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn cAlloc(self: &Allocator, n: usize, alignment: u29) -> %[]u8 {
|
fn cAlloc(self: &Allocator, n: usize, alignment: u29) %[]u8 {
|
||||||
return if (c.malloc(usize(n))) |buf|
|
return if (c.malloc(usize(n))) |buf|
|
||||||
@ptrCast(&u8, buf)[0..n]
|
@ptrCast(&u8, buf)[0..n]
|
||||||
else
|
else
|
||||||
error.OutOfMemory;
|
error.OutOfMemory;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cRealloc(self: &Allocator, old_mem: []u8, new_size: usize, alignment: u29) -> %[]u8 {
|
fn cRealloc(self: &Allocator, old_mem: []u8, new_size: usize, alignment: u29) %[]u8 {
|
||||||
const old_ptr = @ptrCast(&c_void, old_mem.ptr);
|
const old_ptr = @ptrCast(&c_void, old_mem.ptr);
|
||||||
if (c.realloc(old_ptr, new_size)) |buf| {
|
if (c.realloc(old_ptr, new_size)) |buf| {
|
||||||
return @ptrCast(&u8, buf)[0..new_size];
|
return @ptrCast(&u8, buf)[0..new_size];
|
||||||
@ -36,7 +36,7 @@ fn cRealloc(self: &Allocator, old_mem: []u8, new_size: usize, alignment: u29) ->
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cFree(self: &Allocator, old_mem: []u8) {
|
fn cFree(self: &Allocator, old_mem: []u8) void {
|
||||||
const old_ptr = @ptrCast(&c_void, old_mem.ptr);
|
const old_ptr = @ptrCast(&c_void, old_mem.ptr);
|
||||||
c.free(old_ptr);
|
c.free(old_ptr);
|
||||||
}
|
}
|
||||||
@ -47,7 +47,7 @@ pub const IncrementingAllocator = struct {
|
|||||||
end_index: usize,
|
end_index: usize,
|
||||||
heap_handle: if (builtin.os == Os.windows) os.windows.HANDLE else void,
|
heap_handle: if (builtin.os == Os.windows) os.windows.HANDLE else void,
|
||||||
|
|
||||||
fn init(capacity: usize) -> %IncrementingAllocator {
|
fn init(capacity: usize) %IncrementingAllocator {
|
||||||
switch (builtin.os) {
|
switch (builtin.os) {
|
||||||
Os.linux, Os.macosx, Os.ios => {
|
Os.linux, Os.macosx, Os.ios => {
|
||||||
const p = os.posix;
|
const p = os.posix;
|
||||||
@ -85,7 +85,7 @@ pub const IncrementingAllocator = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deinit(self: &IncrementingAllocator) {
|
fn deinit(self: &IncrementingAllocator) void {
|
||||||
switch (builtin.os) {
|
switch (builtin.os) {
|
||||||
Os.linux, Os.macosx, Os.ios => {
|
Os.linux, Os.macosx, Os.ios => {
|
||||||
_ = os.posix.munmap(self.bytes.ptr, self.bytes.len);
|
_ = os.posix.munmap(self.bytes.ptr, self.bytes.len);
|
||||||
@ -97,15 +97,15 @@ pub const IncrementingAllocator = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reset(self: &IncrementingAllocator) {
|
fn reset(self: &IncrementingAllocator) void {
|
||||||
self.end_index = 0;
|
self.end_index = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bytesLeft(self: &const IncrementingAllocator) -> usize {
|
fn bytesLeft(self: &const IncrementingAllocator) usize {
|
||||||
return self.bytes.len - self.end_index;
|
return self.bytes.len - self.end_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn alloc(allocator: &Allocator, n: usize, alignment: u29) -> %[]u8 {
|
fn alloc(allocator: &Allocator, n: usize, alignment: u29) %[]u8 {
|
||||||
const self = @fieldParentPtr(IncrementingAllocator, "allocator", allocator);
|
const self = @fieldParentPtr(IncrementingAllocator, "allocator", allocator);
|
||||||
const addr = @ptrToInt(&self.bytes[self.end_index]);
|
const addr = @ptrToInt(&self.bytes[self.end_index]);
|
||||||
const rem = @rem(addr, alignment);
|
const rem = @rem(addr, alignment);
|
||||||
@ -120,7 +120,7 @@ pub const IncrementingAllocator = struct {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn realloc(allocator: &Allocator, old_mem: []u8, new_size: usize, alignment: u29) -> %[]u8 {
|
fn realloc(allocator: &Allocator, old_mem: []u8, new_size: usize, alignment: u29) %[]u8 {
|
||||||
if (new_size <= old_mem.len) {
|
if (new_size <= old_mem.len) {
|
||||||
return old_mem[0..new_size];
|
return old_mem[0..new_size];
|
||||||
} else {
|
} else {
|
||||||
@ -130,7 +130,7 @@ pub const IncrementingAllocator = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn free(allocator: &Allocator, bytes: []u8) {
|
fn free(allocator: &Allocator, bytes: []u8) void {
|
||||||
// Do nothing. That's the point of an incrementing allocator.
|
// Do nothing. That's the point of an incrementing allocator.
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
98
std/io.zig
98
std/io.zig
@ -50,7 +50,7 @@ error Unseekable;
|
|||||||
error EndOfFile;
|
error EndOfFile;
|
||||||
error FilePosLargerThanPointerRange;
|
error FilePosLargerThanPointerRange;
|
||||||
|
|
||||||
pub fn getStdErr() -> %File {
|
pub fn getStdErr() %File {
|
||||||
const handle = if (is_windows)
|
const handle = if (is_windows)
|
||||||
try os.windowsGetStdHandle(system.STD_ERROR_HANDLE)
|
try os.windowsGetStdHandle(system.STD_ERROR_HANDLE)
|
||||||
else if (is_posix)
|
else if (is_posix)
|
||||||
@ -60,7 +60,7 @@ pub fn getStdErr() -> %File {
|
|||||||
return File.openHandle(handle);
|
return File.openHandle(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getStdOut() -> %File {
|
pub fn getStdOut() %File {
|
||||||
const handle = if (is_windows)
|
const handle = if (is_windows)
|
||||||
try os.windowsGetStdHandle(system.STD_OUTPUT_HANDLE)
|
try os.windowsGetStdHandle(system.STD_OUTPUT_HANDLE)
|
||||||
else if (is_posix)
|
else if (is_posix)
|
||||||
@ -70,7 +70,7 @@ pub fn getStdOut() -> %File {
|
|||||||
return File.openHandle(handle);
|
return File.openHandle(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getStdIn() -> %File {
|
pub fn getStdIn() %File {
|
||||||
const handle = if (is_windows)
|
const handle = if (is_windows)
|
||||||
try os.windowsGetStdHandle(system.STD_INPUT_HANDLE)
|
try os.windowsGetStdHandle(system.STD_INPUT_HANDLE)
|
||||||
else if (is_posix)
|
else if (is_posix)
|
||||||
@ -85,7 +85,7 @@ pub const FileInStream = struct {
|
|||||||
file: &File,
|
file: &File,
|
||||||
stream: InStream,
|
stream: InStream,
|
||||||
|
|
||||||
pub fn init(file: &File) -> FileInStream {
|
pub fn init(file: &File) FileInStream {
|
||||||
return FileInStream {
|
return FileInStream {
|
||||||
.file = file,
|
.file = file,
|
||||||
.stream = InStream {
|
.stream = InStream {
|
||||||
@ -94,7 +94,7 @@ pub const FileInStream = struct {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn readFn(in_stream: &InStream, buffer: []u8) -> %usize {
|
fn readFn(in_stream: &InStream, buffer: []u8) %usize {
|
||||||
const self = @fieldParentPtr(FileInStream, "stream", in_stream);
|
const self = @fieldParentPtr(FileInStream, "stream", in_stream);
|
||||||
return self.file.read(buffer);
|
return self.file.read(buffer);
|
||||||
}
|
}
|
||||||
@ -105,7 +105,7 @@ pub const FileOutStream = struct {
|
|||||||
file: &File,
|
file: &File,
|
||||||
stream: OutStream,
|
stream: OutStream,
|
||||||
|
|
||||||
pub fn init(file: &File) -> FileOutStream {
|
pub fn init(file: &File) FileOutStream {
|
||||||
return FileOutStream {
|
return FileOutStream {
|
||||||
.file = file,
|
.file = file,
|
||||||
.stream = OutStream {
|
.stream = OutStream {
|
||||||
@ -114,7 +114,7 @@ pub const FileOutStream = struct {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn writeFn(out_stream: &OutStream, bytes: []const u8) -> %void {
|
fn writeFn(out_stream: &OutStream, bytes: []const u8) %void {
|
||||||
const self = @fieldParentPtr(FileOutStream, "stream", out_stream);
|
const self = @fieldParentPtr(FileOutStream, "stream", out_stream);
|
||||||
return self.file.write(bytes);
|
return self.file.write(bytes);
|
||||||
}
|
}
|
||||||
@ -129,7 +129,7 @@ pub const File = struct {
|
|||||||
/// size buffer is too small, and the provided allocator is null, error.NameTooLong is returned.
|
/// size buffer is too small, and the provided allocator is null, error.NameTooLong is returned.
|
||||||
/// otherwise if the fixed size buffer is too small, allocator is used to obtain the needed memory.
|
/// otherwise if the fixed size buffer is too small, allocator is used to obtain the needed memory.
|
||||||
/// Call close to clean up.
|
/// Call close to clean up.
|
||||||
pub fn openRead(path: []const u8, allocator: ?&mem.Allocator) -> %File {
|
pub fn openRead(path: []const u8, allocator: ?&mem.Allocator) %File {
|
||||||
if (is_posix) {
|
if (is_posix) {
|
||||||
const flags = system.O_LARGEFILE|system.O_RDONLY;
|
const flags = system.O_LARGEFILE|system.O_RDONLY;
|
||||||
const fd = try os.posixOpen(path, flags, 0, allocator);
|
const fd = try os.posixOpen(path, flags, 0, allocator);
|
||||||
@ -144,7 +144,7 @@ pub const File = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Calls `openWriteMode` with 0o666 for the mode.
|
/// Calls `openWriteMode` with 0o666 for the mode.
|
||||||
pub fn openWrite(path: []const u8, allocator: ?&mem.Allocator) -> %File {
|
pub fn openWrite(path: []const u8, allocator: ?&mem.Allocator) %File {
|
||||||
return openWriteMode(path, 0o666, allocator);
|
return openWriteMode(path, 0o666, allocator);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -154,7 +154,7 @@ pub const File = struct {
|
|||||||
/// size buffer is too small, and the provided allocator is null, error.NameTooLong is returned.
|
/// size buffer is too small, and the provided allocator is null, error.NameTooLong is returned.
|
||||||
/// otherwise if the fixed size buffer is too small, allocator is used to obtain the needed memory.
|
/// otherwise if the fixed size buffer is too small, allocator is used to obtain the needed memory.
|
||||||
/// Call close to clean up.
|
/// Call close to clean up.
|
||||||
pub fn openWriteMode(path: []const u8, mode: usize, allocator: ?&mem.Allocator) -> %File {
|
pub fn openWriteMode(path: []const u8, mode: usize, allocator: ?&mem.Allocator) %File {
|
||||||
if (is_posix) {
|
if (is_posix) {
|
||||||
const flags = system.O_LARGEFILE|system.O_WRONLY|system.O_CREAT|system.O_CLOEXEC|system.O_TRUNC;
|
const flags = system.O_LARGEFILE|system.O_WRONLY|system.O_CREAT|system.O_CLOEXEC|system.O_TRUNC;
|
||||||
const fd = try os.posixOpen(path, flags, mode, allocator);
|
const fd = try os.posixOpen(path, flags, mode, allocator);
|
||||||
@ -170,7 +170,7 @@ pub const File = struct {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn openHandle(handle: os.FileHandle) -> File {
|
pub fn openHandle(handle: os.FileHandle) File {
|
||||||
return File {
|
return File {
|
||||||
.handle = handle,
|
.handle = handle,
|
||||||
};
|
};
|
||||||
@ -179,17 +179,17 @@ pub const File = struct {
|
|||||||
|
|
||||||
/// Upon success, the stream is in an uninitialized state. To continue using it,
|
/// Upon success, the stream is in an uninitialized state. To continue using it,
|
||||||
/// you must use the open() function.
|
/// you must use the open() function.
|
||||||
pub fn close(self: &File) {
|
pub fn close(self: &File) void {
|
||||||
os.close(self.handle);
|
os.close(self.handle);
|
||||||
self.handle = undefined;
|
self.handle = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calls `os.isTty` on `self.handle`.
|
/// Calls `os.isTty` on `self.handle`.
|
||||||
pub fn isTty(self: &File) -> bool {
|
pub fn isTty(self: &File) bool {
|
||||||
return os.isTty(self.handle);
|
return os.isTty(self.handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn seekForward(self: &File, amount: isize) -> %void {
|
pub fn seekForward(self: &File, amount: isize) %void {
|
||||||
switch (builtin.os) {
|
switch (builtin.os) {
|
||||||
Os.linux, Os.macosx, Os.ios => {
|
Os.linux, Os.macosx, Os.ios => {
|
||||||
const result = system.lseek(self.handle, amount, system.SEEK_CUR);
|
const result = system.lseek(self.handle, amount, system.SEEK_CUR);
|
||||||
@ -218,7 +218,7 @@ pub const File = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn seekTo(self: &File, pos: usize) -> %void {
|
pub fn seekTo(self: &File, pos: usize) %void {
|
||||||
switch (builtin.os) {
|
switch (builtin.os) {
|
||||||
Os.linux, Os.macosx, Os.ios => {
|
Os.linux, Os.macosx, Os.ios => {
|
||||||
const ipos = try math.cast(isize, pos);
|
const ipos = try math.cast(isize, pos);
|
||||||
@ -249,7 +249,7 @@ pub const File = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getPos(self: &File) -> %usize {
|
pub fn getPos(self: &File) %usize {
|
||||||
switch (builtin.os) {
|
switch (builtin.os) {
|
||||||
Os.linux, Os.macosx, Os.ios => {
|
Os.linux, Os.macosx, Os.ios => {
|
||||||
const result = system.lseek(self.handle, 0, system.SEEK_CUR);
|
const result = system.lseek(self.handle, 0, system.SEEK_CUR);
|
||||||
@ -289,7 +289,7 @@ pub const File = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getEndPos(self: &File) -> %usize {
|
pub fn getEndPos(self: &File) %usize {
|
||||||
if (is_posix) {
|
if (is_posix) {
|
||||||
var stat: system.Stat = undefined;
|
var stat: system.Stat = undefined;
|
||||||
const err = system.getErrno(system.fstat(self.handle, &stat));
|
const err = system.getErrno(system.fstat(self.handle, &stat));
|
||||||
@ -318,7 +318,7 @@ pub const File = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read(self: &File, buffer: []u8) -> %usize {
|
pub fn read(self: &File, buffer: []u8) %usize {
|
||||||
if (is_posix) {
|
if (is_posix) {
|
||||||
var index: usize = 0;
|
var index: usize = 0;
|
||||||
while (index < buffer.len) {
|
while (index < buffer.len) {
|
||||||
@ -360,7 +360,7 @@ pub const File = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write(self: &File, bytes: []const u8) -> %void {
|
fn write(self: &File, bytes: []const u8) %void {
|
||||||
if (is_posix) {
|
if (is_posix) {
|
||||||
try os.posixWrite(self.handle, bytes);
|
try os.posixWrite(self.handle, bytes);
|
||||||
} else if (is_windows) {
|
} else if (is_windows) {
|
||||||
@ -378,12 +378,12 @@ pub const InStream = struct {
|
|||||||
/// Return the number of bytes read. If the number read is smaller than buf.len, it
|
/// Return the number of bytes read. If the number read is smaller than buf.len, it
|
||||||
/// means the stream reached the end. Reaching the end of a stream is not an error
|
/// means the stream reached the end. Reaching the end of a stream is not an error
|
||||||
/// condition.
|
/// condition.
|
||||||
readFn: fn(self: &InStream, buffer: []u8) -> %usize,
|
readFn: fn(self: &InStream, buffer: []u8) %usize,
|
||||||
|
|
||||||
/// Replaces `buffer` contents by reading from the stream until it is finished.
|
/// Replaces `buffer` contents by reading from the stream until it is finished.
|
||||||
/// If `buffer.len()` would exceed `max_size`, `error.StreamTooLong` is returned and
|
/// If `buffer.len()` would exceed `max_size`, `error.StreamTooLong` is returned and
|
||||||
/// the contents read from the stream are lost.
|
/// the contents read from the stream are lost.
|
||||||
pub fn readAllBuffer(self: &InStream, buffer: &Buffer, max_size: usize) -> %void {
|
pub fn readAllBuffer(self: &InStream, buffer: &Buffer, max_size: usize) %void {
|
||||||
try buffer.resize(0);
|
try buffer.resize(0);
|
||||||
|
|
||||||
var actual_buf_len: usize = 0;
|
var actual_buf_len: usize = 0;
|
||||||
@ -408,7 +408,7 @@ pub const InStream = struct {
|
|||||||
/// memory would be greater than `max_size`, returns `error.StreamTooLong`.
|
/// memory would be greater than `max_size`, returns `error.StreamTooLong`.
|
||||||
/// Caller owns returned memory.
|
/// Caller owns returned memory.
|
||||||
/// If this function returns an error, the contents from the stream read so far are lost.
|
/// If this function returns an error, the contents from the stream read so far are lost.
|
||||||
pub fn readAllAlloc(self: &InStream, allocator: &mem.Allocator, max_size: usize) -> %[]u8 {
|
pub fn readAllAlloc(self: &InStream, allocator: &mem.Allocator, max_size: usize) %[]u8 {
|
||||||
var buf = Buffer.initNull(allocator);
|
var buf = Buffer.initNull(allocator);
|
||||||
defer buf.deinit();
|
defer buf.deinit();
|
||||||
|
|
||||||
@ -420,7 +420,7 @@ pub const InStream = struct {
|
|||||||
/// Does not include the delimiter in the result.
|
/// Does not include the delimiter in the result.
|
||||||
/// If `buffer.len()` would exceed `max_size`, `error.StreamTooLong` is returned and the contents
|
/// If `buffer.len()` would exceed `max_size`, `error.StreamTooLong` is returned and the contents
|
||||||
/// read from the stream so far are lost.
|
/// read from the stream so far are lost.
|
||||||
pub fn readUntilDelimiterBuffer(self: &InStream, buffer: &Buffer, delimiter: u8, max_size: usize) -> %void {
|
pub fn readUntilDelimiterBuffer(self: &InStream, buffer: &Buffer, delimiter: u8, max_size: usize) %void {
|
||||||
try buf.resize(0);
|
try buf.resize(0);
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
@ -443,7 +443,7 @@ pub const InStream = struct {
|
|||||||
/// Caller owns returned memory.
|
/// Caller owns returned memory.
|
||||||
/// If this function returns an error, the contents from the stream read so far are lost.
|
/// If this function returns an error, the contents from the stream read so far are lost.
|
||||||
pub fn readUntilDelimiterAlloc(self: &InStream, allocator: &mem.Allocator,
|
pub fn readUntilDelimiterAlloc(self: &InStream, allocator: &mem.Allocator,
|
||||||
delimiter: u8, max_size: usize) -> %[]u8
|
delimiter: u8, max_size: usize) %[]u8
|
||||||
{
|
{
|
||||||
var buf = Buffer.initNull(allocator);
|
var buf = Buffer.initNull(allocator);
|
||||||
defer buf.deinit();
|
defer buf.deinit();
|
||||||
@ -455,43 +455,43 @@ pub const InStream = struct {
|
|||||||
/// Returns the number of bytes read. If the number read is smaller than buf.len, it
|
/// Returns the number of bytes read. If the number read is smaller than buf.len, it
|
||||||
/// means the stream reached the end. Reaching the end of a stream is not an error
|
/// means the stream reached the end. Reaching the end of a stream is not an error
|
||||||
/// condition.
|
/// condition.
|
||||||
pub fn read(self: &InStream, buffer: []u8) -> %usize {
|
pub fn read(self: &InStream, buffer: []u8) %usize {
|
||||||
return self.readFn(self, buffer);
|
return self.readFn(self, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Same as `read` but end of stream returns `error.EndOfStream`.
|
/// Same as `read` but end of stream returns `error.EndOfStream`.
|
||||||
pub fn readNoEof(self: &InStream, buf: []u8) -> %void {
|
pub fn readNoEof(self: &InStream, buf: []u8) %void {
|
||||||
const amt_read = try self.read(buf);
|
const amt_read = try self.read(buf);
|
||||||
if (amt_read < buf.len) return error.EndOfStream;
|
if (amt_read < buf.len) return error.EndOfStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reads 1 byte from the stream or returns `error.EndOfStream`.
|
/// Reads 1 byte from the stream or returns `error.EndOfStream`.
|
||||||
pub fn readByte(self: &InStream) -> %u8 {
|
pub fn readByte(self: &InStream) %u8 {
|
||||||
var result: [1]u8 = undefined;
|
var result: [1]u8 = undefined;
|
||||||
try self.readNoEof(result[0..]);
|
try self.readNoEof(result[0..]);
|
||||||
return result[0];
|
return result[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Same as `readByte` except the returned byte is signed.
|
/// Same as `readByte` except the returned byte is signed.
|
||||||
pub fn readByteSigned(self: &InStream) -> %i8 {
|
pub fn readByteSigned(self: &InStream) %i8 {
|
||||||
return @bitCast(i8, try self.readByte());
|
return @bitCast(i8, try self.readByte());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn readIntLe(self: &InStream, comptime T: type) -> %T {
|
pub fn readIntLe(self: &InStream, comptime T: type) %T {
|
||||||
return self.readInt(builtin.Endian.Little, T);
|
return self.readInt(builtin.Endian.Little, T);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn readIntBe(self: &InStream, comptime T: type) -> %T {
|
pub fn readIntBe(self: &InStream, comptime T: type) %T {
|
||||||
return self.readInt(builtin.Endian.Big, T);
|
return self.readInt(builtin.Endian.Big, T);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn readInt(self: &InStream, endian: builtin.Endian, comptime T: type) -> %T {
|
pub fn readInt(self: &InStream, endian: builtin.Endian, comptime T: type) %T {
|
||||||
var bytes: [@sizeOf(T)]u8 = undefined;
|
var bytes: [@sizeOf(T)]u8 = undefined;
|
||||||
try self.readNoEof(bytes[0..]);
|
try self.readNoEof(bytes[0..]);
|
||||||
return mem.readInt(bytes, T, endian);
|
return mem.readInt(bytes, T, endian);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn readVarInt(self: &InStream, endian: builtin.Endian, comptime T: type, size: usize) -> %T {
|
pub fn readVarInt(self: &InStream, endian: builtin.Endian, comptime T: type, size: usize) %T {
|
||||||
assert(size <= @sizeOf(T));
|
assert(size <= @sizeOf(T));
|
||||||
assert(size <= 8);
|
assert(size <= 8);
|
||||||
var input_buf: [8]u8 = undefined;
|
var input_buf: [8]u8 = undefined;
|
||||||
@ -504,22 +504,22 @@ pub const InStream = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub const OutStream = struct {
|
pub const OutStream = struct {
|
||||||
writeFn: fn(self: &OutStream, bytes: []const u8) -> %void,
|
writeFn: fn(self: &OutStream, bytes: []const u8) %void,
|
||||||
|
|
||||||
pub fn print(self: &OutStream, comptime format: []const u8, args: ...) -> %void {
|
pub fn print(self: &OutStream, comptime format: []const u8, args: ...) %void {
|
||||||
return std.fmt.format(self, self.writeFn, format, args);
|
return std.fmt.format(self, self.writeFn, format, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write(self: &OutStream, bytes: []const u8) -> %void {
|
pub fn write(self: &OutStream, bytes: []const u8) %void {
|
||||||
return self.writeFn(self, bytes);
|
return self.writeFn(self, bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn writeByte(self: &OutStream, byte: u8) -> %void {
|
pub fn writeByte(self: &OutStream, byte: u8) %void {
|
||||||
const slice = (&byte)[0..1];
|
const slice = (&byte)[0..1];
|
||||||
return self.writeFn(self, slice);
|
return self.writeFn(self, slice);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn writeByteNTimes(self: &OutStream, byte: u8, n: usize) -> %void {
|
pub fn writeByteNTimes(self: &OutStream, byte: u8, n: usize) %void {
|
||||||
const slice = (&byte)[0..1];
|
const slice = (&byte)[0..1];
|
||||||
var i: usize = 0;
|
var i: usize = 0;
|
||||||
while (i < n) : (i += 1) {
|
while (i < n) : (i += 1) {
|
||||||
@ -532,19 +532,19 @@ pub const OutStream = struct {
|
|||||||
/// a fixed size buffer of size `std.os.max_noalloc_path_len` is an attempted solution. If the fixed
|
/// a fixed size buffer of size `std.os.max_noalloc_path_len` is an attempted solution. If the fixed
|
||||||
/// size buffer is too small, and the provided allocator is null, `error.NameTooLong` is returned.
|
/// size buffer is too small, and the provided allocator is null, `error.NameTooLong` is returned.
|
||||||
/// otherwise if the fixed size buffer is too small, allocator is used to obtain the needed memory.
|
/// otherwise if the fixed size buffer is too small, allocator is used to obtain the needed memory.
|
||||||
pub fn writeFile(path: []const u8, data: []const u8, allocator: ?&mem.Allocator) -> %void {
|
pub fn writeFile(path: []const u8, data: []const u8, allocator: ?&mem.Allocator) %void {
|
||||||
var file = try File.openWrite(path, allocator);
|
var file = try File.openWrite(path, allocator);
|
||||||
defer file.close();
|
defer file.close();
|
||||||
try file.write(data);
|
try file.write(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// On success, caller owns returned buffer.
|
/// On success, caller owns returned buffer.
|
||||||
pub fn readFileAlloc(path: []const u8, allocator: &mem.Allocator) -> %[]u8 {
|
pub fn readFileAlloc(path: []const u8, allocator: &mem.Allocator) %[]u8 {
|
||||||
return readFileAllocExtra(path, allocator, 0);
|
return readFileAllocExtra(path, allocator, 0);
|
||||||
}
|
}
|
||||||
/// On success, caller owns returned buffer.
|
/// On success, caller owns returned buffer.
|
||||||
/// Allocates extra_len extra bytes at the end of the file buffer, which are uninitialized.
|
/// Allocates extra_len extra bytes at the end of the file buffer, which are uninitialized.
|
||||||
pub fn readFileAllocExtra(path: []const u8, allocator: &mem.Allocator, extra_len: usize) -> %[]u8 {
|
pub fn readFileAllocExtra(path: []const u8, allocator: &mem.Allocator, extra_len: usize) %[]u8 {
|
||||||
var file = try File.openRead(path, allocator);
|
var file = try File.openRead(path, allocator);
|
||||||
defer file.close();
|
defer file.close();
|
||||||
|
|
||||||
@ -559,7 +559,7 @@ pub fn readFileAllocExtra(path: []const u8, allocator: &mem.Allocator, extra_len
|
|||||||
|
|
||||||
pub const BufferedInStream = BufferedInStreamCustom(os.page_size);
|
pub const BufferedInStream = BufferedInStreamCustom(os.page_size);
|
||||||
|
|
||||||
pub fn BufferedInStreamCustom(comptime buffer_size: usize) -> type {
|
pub fn BufferedInStreamCustom(comptime buffer_size: usize) type {
|
||||||
return struct {
|
return struct {
|
||||||
const Self = this;
|
const Self = this;
|
||||||
|
|
||||||
@ -571,7 +571,7 @@ pub fn BufferedInStreamCustom(comptime buffer_size: usize) -> type {
|
|||||||
start_index: usize,
|
start_index: usize,
|
||||||
end_index: usize,
|
end_index: usize,
|
||||||
|
|
||||||
pub fn init(unbuffered_in_stream: &InStream) -> Self {
|
pub fn init(unbuffered_in_stream: &InStream) Self {
|
||||||
return Self {
|
return Self {
|
||||||
.unbuffered_in_stream = unbuffered_in_stream,
|
.unbuffered_in_stream = unbuffered_in_stream,
|
||||||
.buffer = undefined,
|
.buffer = undefined,
|
||||||
@ -589,7 +589,7 @@ pub fn BufferedInStreamCustom(comptime buffer_size: usize) -> type {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn readFn(in_stream: &InStream, dest: []u8) -> %usize {
|
fn readFn(in_stream: &InStream, dest: []u8) %usize {
|
||||||
const self = @fieldParentPtr(Self, "stream", in_stream);
|
const self = @fieldParentPtr(Self, "stream", in_stream);
|
||||||
|
|
||||||
var dest_index: usize = 0;
|
var dest_index: usize = 0;
|
||||||
@ -630,7 +630,7 @@ pub fn BufferedInStreamCustom(comptime buffer_size: usize) -> type {
|
|||||||
|
|
||||||
pub const BufferedOutStream = BufferedOutStreamCustom(os.page_size);
|
pub const BufferedOutStream = BufferedOutStreamCustom(os.page_size);
|
||||||
|
|
||||||
pub fn BufferedOutStreamCustom(comptime buffer_size: usize) -> type {
|
pub fn BufferedOutStreamCustom(comptime buffer_size: usize) type {
|
||||||
return struct {
|
return struct {
|
||||||
const Self = this;
|
const Self = this;
|
||||||
|
|
||||||
@ -641,7 +641,7 @@ pub fn BufferedOutStreamCustom(comptime buffer_size: usize) -> type {
|
|||||||
buffer: [buffer_size]u8,
|
buffer: [buffer_size]u8,
|
||||||
index: usize,
|
index: usize,
|
||||||
|
|
||||||
pub fn init(unbuffered_out_stream: &OutStream) -> Self {
|
pub fn init(unbuffered_out_stream: &OutStream) Self {
|
||||||
return Self {
|
return Self {
|
||||||
.unbuffered_out_stream = unbuffered_out_stream,
|
.unbuffered_out_stream = unbuffered_out_stream,
|
||||||
.buffer = undefined,
|
.buffer = undefined,
|
||||||
@ -652,7 +652,7 @@ pub fn BufferedOutStreamCustom(comptime buffer_size: usize) -> type {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn flush(self: &Self) -> %void {
|
pub fn flush(self: &Self) %void {
|
||||||
if (self.index == 0)
|
if (self.index == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -660,7 +660,7 @@ pub fn BufferedOutStreamCustom(comptime buffer_size: usize) -> type {
|
|||||||
self.index = 0;
|
self.index = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn writeFn(out_stream: &OutStream, bytes: []const u8) -> %void {
|
fn writeFn(out_stream: &OutStream, bytes: []const u8) %void {
|
||||||
const self = @fieldParentPtr(Self, "stream", out_stream);
|
const self = @fieldParentPtr(Self, "stream", out_stream);
|
||||||
|
|
||||||
if (bytes.len >= self.buffer.len) {
|
if (bytes.len >= self.buffer.len) {
|
||||||
@ -689,7 +689,7 @@ pub const BufferOutStream = struct {
|
|||||||
buffer: &Buffer,
|
buffer: &Buffer,
|
||||||
stream: OutStream,
|
stream: OutStream,
|
||||||
|
|
||||||
pub fn init(buffer: &Buffer) -> BufferOutStream {
|
pub fn init(buffer: &Buffer) BufferOutStream {
|
||||||
return BufferOutStream {
|
return BufferOutStream {
|
||||||
.buffer = buffer,
|
.buffer = buffer,
|
||||||
.stream = OutStream {
|
.stream = OutStream {
|
||||||
@ -698,7 +698,7 @@ pub const BufferOutStream = struct {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn writeFn(out_stream: &OutStream, bytes: []const u8) -> %void {
|
fn writeFn(out_stream: &OutStream, bytes: []const u8) %void {
|
||||||
const self = @fieldParentPtr(BufferOutStream, "stream", out_stream);
|
const self = @fieldParentPtr(BufferOutStream, "stream", out_stream);
|
||||||
return self.buffer.append(bytes);
|
return self.buffer.append(bytes);
|
||||||
}
|
}
|
||||||
|
@ -5,17 +5,17 @@ const mem = std.mem;
|
|||||||
const Allocator = mem.Allocator;
|
const Allocator = mem.Allocator;
|
||||||
|
|
||||||
/// Generic non-intrusive doubly linked list.
|
/// Generic non-intrusive doubly linked list.
|
||||||
pub fn LinkedList(comptime T: type) -> type {
|
pub fn LinkedList(comptime T: type) type {
|
||||||
return BaseLinkedList(T, void, "");
|
return BaseLinkedList(T, void, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generic intrusive doubly linked list.
|
/// Generic intrusive doubly linked list.
|
||||||
pub fn IntrusiveLinkedList(comptime ParentType: type, comptime field_name: []const u8) -> type {
|
pub fn IntrusiveLinkedList(comptime ParentType: type, comptime field_name: []const u8) type {
|
||||||
return BaseLinkedList(void, ParentType, field_name);
|
return BaseLinkedList(void, ParentType, field_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generic doubly linked list.
|
/// Generic doubly linked list.
|
||||||
fn BaseLinkedList(comptime T: type, comptime ParentType: type, comptime field_name: []const u8) -> type {
|
fn BaseLinkedList(comptime T: type, comptime ParentType: type, comptime field_name: []const u8) type {
|
||||||
return struct {
|
return struct {
|
||||||
const Self = this;
|
const Self = this;
|
||||||
|
|
||||||
@ -25,7 +25,7 @@ fn BaseLinkedList(comptime T: type, comptime ParentType: type, comptime field_na
|
|||||||
next: ?&Node,
|
next: ?&Node,
|
||||||
data: T,
|
data: T,
|
||||||
|
|
||||||
pub fn init(value: &const T) -> Node {
|
pub fn init(value: &const T) Node {
|
||||||
return Node {
|
return Node {
|
||||||
.prev = null,
|
.prev = null,
|
||||||
.next = null,
|
.next = null,
|
||||||
@ -33,12 +33,12 @@ fn BaseLinkedList(comptime T: type, comptime ParentType: type, comptime field_na
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn initIntrusive() -> Node {
|
pub fn initIntrusive() Node {
|
||||||
// TODO: when #678 is solved this can become `init`.
|
// TODO: when #678 is solved this can become `init`.
|
||||||
return Node.init({});
|
return Node.init({});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn toData(node: &Node) -> &ParentType {
|
pub fn toData(node: &Node) &ParentType {
|
||||||
comptime assert(isIntrusive());
|
comptime assert(isIntrusive());
|
||||||
return @fieldParentPtr(ParentType, field_name, node);
|
return @fieldParentPtr(ParentType, field_name, node);
|
||||||
}
|
}
|
||||||
@ -52,7 +52,7 @@ fn BaseLinkedList(comptime T: type, comptime ParentType: type, comptime field_na
|
|||||||
///
|
///
|
||||||
/// Returns:
|
/// Returns:
|
||||||
/// An empty linked list.
|
/// An empty linked list.
|
||||||
pub fn init() -> Self {
|
pub fn init() Self {
|
||||||
return Self {
|
return Self {
|
||||||
.first = null,
|
.first = null,
|
||||||
.last = null,
|
.last = null,
|
||||||
@ -60,7 +60,7 @@ fn BaseLinkedList(comptime T: type, comptime ParentType: type, comptime field_na
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn isIntrusive() -> bool {
|
fn isIntrusive() bool {
|
||||||
return ParentType != void or field_name.len != 0;
|
return ParentType != void or field_name.len != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,7 +69,7 @@ fn BaseLinkedList(comptime T: type, comptime ParentType: type, comptime field_na
|
|||||||
/// Arguments:
|
/// Arguments:
|
||||||
/// node: Pointer to a node in the list.
|
/// node: Pointer to a node in the list.
|
||||||
/// new_node: Pointer to the new node to insert.
|
/// new_node: Pointer to the new node to insert.
|
||||||
pub fn insertAfter(list: &Self, node: &Node, new_node: &Node) {
|
pub fn insertAfter(list: &Self, node: &Node, new_node: &Node) void {
|
||||||
new_node.prev = node;
|
new_node.prev = node;
|
||||||
if (node.next) |next_node| {
|
if (node.next) |next_node| {
|
||||||
// Intermediate node.
|
// Intermediate node.
|
||||||
@ -90,7 +90,7 @@ fn BaseLinkedList(comptime T: type, comptime ParentType: type, comptime field_na
|
|||||||
/// Arguments:
|
/// Arguments:
|
||||||
/// node: Pointer to a node in the list.
|
/// node: Pointer to a node in the list.
|
||||||
/// new_node: Pointer to the new node to insert.
|
/// new_node: Pointer to the new node to insert.
|
||||||
pub fn insertBefore(list: &Self, node: &Node, new_node: &Node) {
|
pub fn insertBefore(list: &Self, node: &Node, new_node: &Node) void {
|
||||||
new_node.next = node;
|
new_node.next = node;
|
||||||
if (node.prev) |prev_node| {
|
if (node.prev) |prev_node| {
|
||||||
// Intermediate node.
|
// Intermediate node.
|
||||||
@ -110,7 +110,7 @@ fn BaseLinkedList(comptime T: type, comptime ParentType: type, comptime field_na
|
|||||||
///
|
///
|
||||||
/// Arguments:
|
/// Arguments:
|
||||||
/// new_node: Pointer to the new node to insert.
|
/// new_node: Pointer to the new node to insert.
|
||||||
pub fn append(list: &Self, new_node: &Node) {
|
pub fn append(list: &Self, new_node: &Node) void {
|
||||||
if (list.last) |last| {
|
if (list.last) |last| {
|
||||||
// Insert after last.
|
// Insert after last.
|
||||||
list.insertAfter(last, new_node);
|
list.insertAfter(last, new_node);
|
||||||
@ -124,7 +124,7 @@ fn BaseLinkedList(comptime T: type, comptime ParentType: type, comptime field_na
|
|||||||
///
|
///
|
||||||
/// Arguments:
|
/// Arguments:
|
||||||
/// new_node: Pointer to the new node to insert.
|
/// new_node: Pointer to the new node to insert.
|
||||||
pub fn prepend(list: &Self, new_node: &Node) {
|
pub fn prepend(list: &Self, new_node: &Node) void {
|
||||||
if (list.first) |first| {
|
if (list.first) |first| {
|
||||||
// Insert before first.
|
// Insert before first.
|
||||||
list.insertBefore(first, new_node);
|
list.insertBefore(first, new_node);
|
||||||
@ -143,7 +143,7 @@ fn BaseLinkedList(comptime T: type, comptime ParentType: type, comptime field_na
|
|||||||
///
|
///
|
||||||
/// Arguments:
|
/// Arguments:
|
||||||
/// node: Pointer to the node to be removed.
|
/// node: Pointer to the node to be removed.
|
||||||
pub fn remove(list: &Self, node: &Node) {
|
pub fn remove(list: &Self, node: &Node) void {
|
||||||
if (node.prev) |prev_node| {
|
if (node.prev) |prev_node| {
|
||||||
// Intermediate node.
|
// Intermediate node.
|
||||||
prev_node.next = node.next;
|
prev_node.next = node.next;
|
||||||
@ -167,7 +167,7 @@ fn BaseLinkedList(comptime T: type, comptime ParentType: type, comptime field_na
|
|||||||
///
|
///
|
||||||
/// Returns:
|
/// Returns:
|
||||||
/// A pointer to the last node in the list.
|
/// A pointer to the last node in the list.
|
||||||
pub fn pop(list: &Self) -> ?&Node {
|
pub fn pop(list: &Self) ?&Node {
|
||||||
const last = list.last ?? return null;
|
const last = list.last ?? return null;
|
||||||
list.remove(last);
|
list.remove(last);
|
||||||
return last;
|
return last;
|
||||||
@ -177,7 +177,7 @@ fn BaseLinkedList(comptime T: type, comptime ParentType: type, comptime field_na
|
|||||||
///
|
///
|
||||||
/// Returns:
|
/// Returns:
|
||||||
/// A pointer to the first node in the list.
|
/// A pointer to the first node in the list.
|
||||||
pub fn popFirst(list: &Self) -> ?&Node {
|
pub fn popFirst(list: &Self) ?&Node {
|
||||||
const first = list.first ?? return null;
|
const first = list.first ?? return null;
|
||||||
list.remove(first);
|
list.remove(first);
|
||||||
return first;
|
return first;
|
||||||
@ -190,7 +190,7 @@ fn BaseLinkedList(comptime T: type, comptime ParentType: type, comptime field_na
|
|||||||
///
|
///
|
||||||
/// Returns:
|
/// Returns:
|
||||||
/// A pointer to the new node.
|
/// A pointer to the new node.
|
||||||
pub fn allocateNode(list: &Self, allocator: &Allocator) -> %&Node {
|
pub fn allocateNode(list: &Self, allocator: &Allocator) %&Node {
|
||||||
comptime assert(!isIntrusive());
|
comptime assert(!isIntrusive());
|
||||||
return allocator.create(Node);
|
return allocator.create(Node);
|
||||||
}
|
}
|
||||||
@ -200,7 +200,7 @@ fn BaseLinkedList(comptime T: type, comptime ParentType: type, comptime field_na
|
|||||||
/// Arguments:
|
/// Arguments:
|
||||||
/// node: Pointer to the node to deallocate.
|
/// node: Pointer to the node to deallocate.
|
||||||
/// allocator: Dynamic memory allocator.
|
/// allocator: Dynamic memory allocator.
|
||||||
pub fn destroyNode(list: &Self, node: &Node, allocator: &Allocator) {
|
pub fn destroyNode(list: &Self, node: &Node, allocator: &Allocator) void {
|
||||||
comptime assert(!isIntrusive());
|
comptime assert(!isIntrusive());
|
||||||
allocator.destroy(node);
|
allocator.destroy(node);
|
||||||
}
|
}
|
||||||
@ -213,7 +213,7 @@ fn BaseLinkedList(comptime T: type, comptime ParentType: type, comptime field_na
|
|||||||
///
|
///
|
||||||
/// Returns:
|
/// Returns:
|
||||||
/// A pointer to the new node.
|
/// A pointer to the new node.
|
||||||
pub fn createNode(list: &Self, data: &const T, allocator: &Allocator) -> %&Node {
|
pub fn createNode(list: &Self, data: &const T, allocator: &Allocator) %&Node {
|
||||||
comptime assert(!isIntrusive());
|
comptime assert(!isIntrusive());
|
||||||
var node = try list.allocateNode(allocator);
|
var node = try list.allocateNode(allocator);
|
||||||
*node = Node.init(data);
|
*node = Node.init(data);
|
||||||
|
@ -6,7 +6,7 @@ const std = @import("../index.zig");
|
|||||||
const math = std.math;
|
const math = std.math;
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
|
|
||||||
pub fn acos(x: var) -> @typeOf(x) {
|
pub fn acos(x: var) @typeOf(x) {
|
||||||
const T = @typeOf(x);
|
const T = @typeOf(x);
|
||||||
return switch (T) {
|
return switch (T) {
|
||||||
f32 => acos32(x),
|
f32 => acos32(x),
|
||||||
@ -15,7 +15,7 @@ pub fn acos(x: var) -> @typeOf(x) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn r32(z: f32) -> f32 {
|
fn r32(z: f32) f32 {
|
||||||
const pS0 = 1.6666586697e-01;
|
const pS0 = 1.6666586697e-01;
|
||||||
const pS1 = -4.2743422091e-02;
|
const pS1 = -4.2743422091e-02;
|
||||||
const pS2 = -8.6563630030e-03;
|
const pS2 = -8.6563630030e-03;
|
||||||
@ -26,7 +26,7 @@ fn r32(z: f32) -> f32 {
|
|||||||
return p / q;
|
return p / q;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn acos32(x: f32) -> f32 {
|
fn acos32(x: f32) f32 {
|
||||||
const pio2_hi = 1.5707962513e+00;
|
const pio2_hi = 1.5707962513e+00;
|
||||||
const pio2_lo = 7.5497894159e-08;
|
const pio2_lo = 7.5497894159e-08;
|
||||||
|
|
||||||
@ -73,7 +73,7 @@ fn acos32(x: f32) -> f32 {
|
|||||||
return 2 * (df + w);
|
return 2 * (df + w);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn r64(z: f64) -> f64 {
|
fn r64(z: f64) f64 {
|
||||||
const pS0: f64 = 1.66666666666666657415e-01;
|
const pS0: f64 = 1.66666666666666657415e-01;
|
||||||
const pS1: f64 = -3.25565818622400915405e-01;
|
const pS1: f64 = -3.25565818622400915405e-01;
|
||||||
const pS2: f64 = 2.01212532134862925881e-01;
|
const pS2: f64 = 2.01212532134862925881e-01;
|
||||||
@ -90,7 +90,7 @@ fn r64(z: f64) -> f64 {
|
|||||||
return p / q;
|
return p / q;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn acos64(x: f64) -> f64 {
|
fn acos64(x: f64) f64 {
|
||||||
const pio2_hi: f64 = 1.57079632679489655800e+00;
|
const pio2_hi: f64 = 1.57079632679489655800e+00;
|
||||||
const pio2_lo: f64 = 6.12323399573676603587e-17;
|
const pio2_lo: f64 = 6.12323399573676603587e-17;
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ const std = @import("../index.zig");
|
|||||||
const math = std.math;
|
const math = std.math;
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
|
|
||||||
pub fn acosh(x: var) -> @typeOf(x) {
|
pub fn acosh(x: var) @typeOf(x) {
|
||||||
const T = @typeOf(x);
|
const T = @typeOf(x);
|
||||||
return switch (T) {
|
return switch (T) {
|
||||||
f32 => acosh32(x),
|
f32 => acosh32(x),
|
||||||
@ -18,7 +18,7 @@ pub fn acosh(x: var) -> @typeOf(x) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// acosh(x) = log(x + sqrt(x * x - 1))
|
// acosh(x) = log(x + sqrt(x * x - 1))
|
||||||
fn acosh32(x: f32) -> f32 {
|
fn acosh32(x: f32) f32 {
|
||||||
const u = @bitCast(u32, x);
|
const u = @bitCast(u32, x);
|
||||||
const i = u & 0x7FFFFFFF;
|
const i = u & 0x7FFFFFFF;
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ fn acosh32(x: f32) -> f32 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn acosh64(x: f64) -> f64 {
|
fn acosh64(x: f64) f64 {
|
||||||
const u = @bitCast(u64, x);
|
const u = @bitCast(u64, x);
|
||||||
const e = (u >> 52) & 0x7FF;
|
const e = (u >> 52) & 0x7FF;
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ const std = @import("../index.zig");
|
|||||||
const math = std.math;
|
const math = std.math;
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
|
|
||||||
pub fn asin(x: var) -> @typeOf(x) {
|
pub fn asin(x: var) @typeOf(x) {
|
||||||
const T = @typeOf(x);
|
const T = @typeOf(x);
|
||||||
return switch (T) {
|
return switch (T) {
|
||||||
f32 => asin32(x),
|
f32 => asin32(x),
|
||||||
@ -16,7 +16,7 @@ pub fn asin(x: var) -> @typeOf(x) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn r32(z: f32) -> f32 {
|
fn r32(z: f32) f32 {
|
||||||
const pS0 = 1.6666586697e-01;
|
const pS0 = 1.6666586697e-01;
|
||||||
const pS1 = -4.2743422091e-02;
|
const pS1 = -4.2743422091e-02;
|
||||||
const pS2 = -8.6563630030e-03;
|
const pS2 = -8.6563630030e-03;
|
||||||
@ -27,7 +27,7 @@ fn r32(z: f32) -> f32 {
|
|||||||
return p / q;
|
return p / q;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn asin32(x: f32) -> f32 {
|
fn asin32(x: f32) f32 {
|
||||||
const pio2 = 1.570796326794896558e+00;
|
const pio2 = 1.570796326794896558e+00;
|
||||||
|
|
||||||
const hx: u32 = @bitCast(u32, x);
|
const hx: u32 = @bitCast(u32, x);
|
||||||
@ -65,7 +65,7 @@ fn asin32(x: f32) -> f32 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn r64(z: f64) -> f64 {
|
fn r64(z: f64) f64 {
|
||||||
const pS0: f64 = 1.66666666666666657415e-01;
|
const pS0: f64 = 1.66666666666666657415e-01;
|
||||||
const pS1: f64 = -3.25565818622400915405e-01;
|
const pS1: f64 = -3.25565818622400915405e-01;
|
||||||
const pS2: f64 = 2.01212532134862925881e-01;
|
const pS2: f64 = 2.01212532134862925881e-01;
|
||||||
@ -82,7 +82,7 @@ fn r64(z: f64) -> f64 {
|
|||||||
return p / q;
|
return p / q;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn asin64(x: f64) -> f64 {
|
fn asin64(x: f64) f64 {
|
||||||
const pio2_hi: f64 = 1.57079632679489655800e+00;
|
const pio2_hi: f64 = 1.57079632679489655800e+00;
|
||||||
const pio2_lo: f64 = 6.12323399573676603587e-17;
|
const pio2_lo: f64 = 6.12323399573676603587e-17;
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ const std = @import("../index.zig");
|
|||||||
const math = std.math;
|
const math = std.math;
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
|
|
||||||
pub fn asinh(x: var) -> @typeOf(x) {
|
pub fn asinh(x: var) @typeOf(x) {
|
||||||
const T = @typeOf(x);
|
const T = @typeOf(x);
|
||||||
return switch (T) {
|
return switch (T) {
|
||||||
f32 => asinh32(x),
|
f32 => asinh32(x),
|
||||||
@ -18,7 +18,7 @@ pub fn asinh(x: var) -> @typeOf(x) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// asinh(x) = sign(x) * log(|x| + sqrt(x * x + 1)) ~= x - x^3/6 + o(x^5)
|
// asinh(x) = sign(x) * log(|x| + sqrt(x * x + 1)) ~= x - x^3/6 + o(x^5)
|
||||||
fn asinh32(x: f32) -> f32 {
|
fn asinh32(x: f32) f32 {
|
||||||
const u = @bitCast(u32, x);
|
const u = @bitCast(u32, x);
|
||||||
const i = u & 0x7FFFFFFF;
|
const i = u & 0x7FFFFFFF;
|
||||||
const s = i >> 31;
|
const s = i >> 31;
|
||||||
@ -50,7 +50,7 @@ fn asinh32(x: f32) -> f32 {
|
|||||||
return if (s != 0) -rx else rx;
|
return if (s != 0) -rx else rx;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn asinh64(x: f64) -> f64 {
|
fn asinh64(x: f64) f64 {
|
||||||
const u = @bitCast(u64, x);
|
const u = @bitCast(u64, x);
|
||||||
const e = (u >> 52) & 0x7FF;
|
const e = (u >> 52) & 0x7FF;
|
||||||
const s = u >> 63;
|
const s = u >> 63;
|
||||||
|
@ -7,7 +7,7 @@ const std = @import("../index.zig");
|
|||||||
const math = std.math;
|
const math = std.math;
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
|
|
||||||
pub fn atan(x: var) -> @typeOf(x) {
|
pub fn atan(x: var) @typeOf(x) {
|
||||||
const T = @typeOf(x);
|
const T = @typeOf(x);
|
||||||
return switch (T) {
|
return switch (T) {
|
||||||
f32 => atan32(x),
|
f32 => atan32(x),
|
||||||
@ -16,7 +16,7 @@ pub fn atan(x: var) -> @typeOf(x) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn atan32(x_: f32) -> f32 {
|
fn atan32(x_: f32) f32 {
|
||||||
const atanhi = []const f32 {
|
const atanhi = []const f32 {
|
||||||
4.6364760399e-01, // atan(0.5)hi
|
4.6364760399e-01, // atan(0.5)hi
|
||||||
7.8539812565e-01, // atan(1.0)hi
|
7.8539812565e-01, // atan(1.0)hi
|
||||||
@ -108,7 +108,7 @@ fn atan32(x_: f32) -> f32 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn atan64(x_: f64) -> f64 {
|
fn atan64(x_: f64) f64 {
|
||||||
const atanhi = []const f64 {
|
const atanhi = []const f64 {
|
||||||
4.63647609000806093515e-01, // atan(0.5)hi
|
4.63647609000806093515e-01, // atan(0.5)hi
|
||||||
7.85398163397448278999e-01, // atan(1.0)hi
|
7.85398163397448278999e-01, // atan(1.0)hi
|
||||||
|
@ -22,7 +22,7 @@ const std = @import("../index.zig");
|
|||||||
const math = std.math;
|
const math = std.math;
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
|
|
||||||
fn atan2(comptime T: type, x: T, y: T) -> T {
|
fn atan2(comptime T: type, x: T, y: T) T {
|
||||||
return switch (T) {
|
return switch (T) {
|
||||||
f32 => atan2_32(x, y),
|
f32 => atan2_32(x, y),
|
||||||
f64 => atan2_64(x, y),
|
f64 => atan2_64(x, y),
|
||||||
@ -30,7 +30,7 @@ fn atan2(comptime T: type, x: T, y: T) -> T {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn atan2_32(y: f32, x: f32) -> f32 {
|
fn atan2_32(y: f32, x: f32) f32 {
|
||||||
const pi: f32 = 3.1415927410e+00;
|
const pi: f32 = 3.1415927410e+00;
|
||||||
const pi_lo: f32 = -8.7422776573e-08;
|
const pi_lo: f32 = -8.7422776573e-08;
|
||||||
|
|
||||||
@ -115,7 +115,7 @@ fn atan2_32(y: f32, x: f32) -> f32 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn atan2_64(y: f64, x: f64) -> f64 {
|
fn atan2_64(y: f64, x: f64) f64 {
|
||||||
const pi: f64 = 3.1415926535897931160E+00;
|
const pi: f64 = 3.1415926535897931160E+00;
|
||||||
const pi_lo: f64 = 1.2246467991473531772E-16;
|
const pi_lo: f64 = 1.2246467991473531772E-16;
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ const std = @import("../index.zig");
|
|||||||
const math = std.math;
|
const math = std.math;
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
|
|
||||||
pub fn atanh(x: var) -> @typeOf(x) {
|
pub fn atanh(x: var) @typeOf(x) {
|
||||||
const T = @typeOf(x);
|
const T = @typeOf(x);
|
||||||
return switch (T) {
|
return switch (T) {
|
||||||
f32 => atanh_32(x),
|
f32 => atanh_32(x),
|
||||||
@ -18,7 +18,7 @@ pub fn atanh(x: var) -> @typeOf(x) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// atanh(x) = log((1 + x) / (1 - x)) / 2 = log1p(2x / (1 - x)) / 2 ~= x + x^3 / 3 + o(x^5)
|
// atanh(x) = log((1 + x) / (1 - x)) / 2 = log1p(2x / (1 - x)) / 2 ~= x + x^3 / 3 + o(x^5)
|
||||||
fn atanh_32(x: f32) -> f32 {
|
fn atanh_32(x: f32) f32 {
|
||||||
const u = @bitCast(u32, x);
|
const u = @bitCast(u32, x);
|
||||||
const i = u & 0x7FFFFFFF;
|
const i = u & 0x7FFFFFFF;
|
||||||
const s = u >> 31;
|
const s = u >> 31;
|
||||||
@ -47,7 +47,7 @@ fn atanh_32(x: f32) -> f32 {
|
|||||||
return if (s != 0) -y else y;
|
return if (s != 0) -y else y;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn atanh_64(x: f64) -> f64 {
|
fn atanh_64(x: f64) f64 {
|
||||||
const u = @bitCast(u64, x);
|
const u = @bitCast(u64, x);
|
||||||
const e = (u >> 52) & 0x7FF;
|
const e = (u >> 52) & 0x7FF;
|
||||||
const s = u >> 63;
|
const s = u >> 63;
|
||||||
|
@ -8,7 +8,7 @@ const std = @import("../index.zig");
|
|||||||
const math = std.math;
|
const math = std.math;
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
|
|
||||||
pub fn cbrt(x: var) -> @typeOf(x) {
|
pub fn cbrt(x: var) @typeOf(x) {
|
||||||
const T = @typeOf(x);
|
const T = @typeOf(x);
|
||||||
return switch (T) {
|
return switch (T) {
|
||||||
f32 => cbrt32(x),
|
f32 => cbrt32(x),
|
||||||
@ -17,7 +17,7 @@ pub fn cbrt(x: var) -> @typeOf(x) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cbrt32(x: f32) -> f32 {
|
fn cbrt32(x: f32) f32 {
|
||||||
const B1: u32 = 709958130; // (127 - 127.0 / 3 - 0.03306235651) * 2^23
|
const B1: u32 = 709958130; // (127 - 127.0 / 3 - 0.03306235651) * 2^23
|
||||||
const B2: u32 = 642849266; // (127 - 127.0 / 3 - 24 / 3 - 0.03306235651) * 2^23
|
const B2: u32 = 642849266; // (127 - 127.0 / 3 - 24 / 3 - 0.03306235651) * 2^23
|
||||||
|
|
||||||
@ -57,7 +57,7 @@ fn cbrt32(x: f32) -> f32 {
|
|||||||
return f32(t);
|
return f32(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cbrt64(x: f64) -> f64 {
|
fn cbrt64(x: f64) f64 {
|
||||||
const B1: u32 = 715094163; // (1023 - 1023 / 3 - 0.03306235651 * 2^20
|
const B1: u32 = 715094163; // (1023 - 1023 / 3 - 0.03306235651 * 2^20
|
||||||
const B2: u32 = 696219795; // (1023 - 1023 / 3 - 54 / 3 - 0.03306235651 * 2^20
|
const B2: u32 = 696219795; // (1023 - 1023 / 3 - 54 / 3 - 0.03306235651 * 2^20
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ const std = @import("../index.zig");
|
|||||||
const math = std.math;
|
const math = std.math;
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
|
|
||||||
pub fn ceil(x: var) -> @typeOf(x) {
|
pub fn ceil(x: var) @typeOf(x) {
|
||||||
const T = @typeOf(x);
|
const T = @typeOf(x);
|
||||||
return switch (T) {
|
return switch (T) {
|
||||||
f32 => ceil32(x),
|
f32 => ceil32(x),
|
||||||
@ -18,7 +18,7 @@ pub fn ceil(x: var) -> @typeOf(x) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ceil32(x: f32) -> f32 {
|
fn ceil32(x: f32) f32 {
|
||||||
var u = @bitCast(u32, x);
|
var u = @bitCast(u32, x);
|
||||||
var e = i32((u >> 23) & 0xFF) - 0x7F;
|
var e = i32((u >> 23) & 0xFF) - 0x7F;
|
||||||
var m: u32 = undefined;
|
var m: u32 = undefined;
|
||||||
@ -51,7 +51,7 @@ fn ceil32(x: f32) -> f32 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ceil64(x: f64) -> f64 {
|
fn ceil64(x: f64) f64 {
|
||||||
const u = @bitCast(u64, x);
|
const u = @bitCast(u64, x);
|
||||||
const e = (u >> 52) & 0x7FF;
|
const e = (u >> 52) & 0x7FF;
|
||||||
var y: f64 = undefined;
|
var y: f64 = undefined;
|
||||||
|
@ -2,7 +2,7 @@ const std = @import("../index.zig");
|
|||||||
const math = std.math;
|
const math = std.math;
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
|
|
||||||
pub fn copysign(comptime T: type, x: T, y: T) -> T {
|
pub fn copysign(comptime T: type, x: T, y: T) T {
|
||||||
return switch (T) {
|
return switch (T) {
|
||||||
f32 => copysign32(x, y),
|
f32 => copysign32(x, y),
|
||||||
f64 => copysign64(x, y),
|
f64 => copysign64(x, y),
|
||||||
@ -10,7 +10,7 @@ pub fn copysign(comptime T: type, x: T, y: T) -> T {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn copysign32(x: f32, y: f32) -> f32 {
|
fn copysign32(x: f32, y: f32) f32 {
|
||||||
const ux = @bitCast(u32, x);
|
const ux = @bitCast(u32, x);
|
||||||
const uy = @bitCast(u32, y);
|
const uy = @bitCast(u32, y);
|
||||||
|
|
||||||
@ -19,7 +19,7 @@ fn copysign32(x: f32, y: f32) -> f32 {
|
|||||||
return @bitCast(f32, h1 | h2);
|
return @bitCast(f32, h1 | h2);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn copysign64(x: f64, y: f64) -> f64 {
|
fn copysign64(x: f64, y: f64) f64 {
|
||||||
const ux = @bitCast(u64, x);
|
const ux = @bitCast(u64, x);
|
||||||
const uy = @bitCast(u64, y);
|
const uy = @bitCast(u64, y);
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ const std = @import("../index.zig");
|
|||||||
const math = std.math;
|
const math = std.math;
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
|
|
||||||
pub fn cos(x: var) -> @typeOf(x) {
|
pub fn cos(x: var) @typeOf(x) {
|
||||||
const T = @typeOf(x);
|
const T = @typeOf(x);
|
||||||
return switch (T) {
|
return switch (T) {
|
||||||
f32 => cos32(x),
|
f32 => cos32(x),
|
||||||
@ -36,7 +36,7 @@ const C5 = 4.16666666666665929218E-2;
|
|||||||
// NOTE: This is taken from the go stdlib. The musl implementation is much more complex.
|
// NOTE: This is taken from the go stdlib. The musl implementation is much more complex.
|
||||||
//
|
//
|
||||||
// This may have slight differences on some edge cases and may need to replaced if so.
|
// This may have slight differences on some edge cases and may need to replaced if so.
|
||||||
fn cos32(x_: f32) -> f32 {
|
fn cos32(x_: f32) f32 {
|
||||||
@setFloatMode(this, @import("builtin").FloatMode.Strict);
|
@setFloatMode(this, @import("builtin").FloatMode.Strict);
|
||||||
|
|
||||||
const pi4a = 7.85398125648498535156e-1;
|
const pi4a = 7.85398125648498535156e-1;
|
||||||
@ -89,7 +89,7 @@ fn cos32(x_: f32) -> f32 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cos64(x_: f64) -> f64 {
|
fn cos64(x_: f64) f64 {
|
||||||
const pi4a = 7.85398125648498535156e-1;
|
const pi4a = 7.85398125648498535156e-1;
|
||||||
const pi4b = 3.77489470793079817668E-8;
|
const pi4b = 3.77489470793079817668E-8;
|
||||||
const pi4c = 2.69515142907905952645E-15;
|
const pi4c = 2.69515142907905952645E-15;
|
||||||
|
@ -10,7 +10,7 @@ const math = std.math;
|
|||||||
const expo2 = @import("expo2.zig").expo2;
|
const expo2 = @import("expo2.zig").expo2;
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
|
|
||||||
pub fn cosh(x: var) -> @typeOf(x) {
|
pub fn cosh(x: var) @typeOf(x) {
|
||||||
const T = @typeOf(x);
|
const T = @typeOf(x);
|
||||||
return switch (T) {
|
return switch (T) {
|
||||||
f32 => cosh32(x),
|
f32 => cosh32(x),
|
||||||
@ -22,7 +22,7 @@ pub fn cosh(x: var) -> @typeOf(x) {
|
|||||||
// cosh(x) = (exp(x) + 1 / exp(x)) / 2
|
// cosh(x) = (exp(x) + 1 / exp(x)) / 2
|
||||||
// = 1 + 0.5 * (exp(x) - 1) * (exp(x) - 1) / exp(x)
|
// = 1 + 0.5 * (exp(x) - 1) * (exp(x) - 1) / exp(x)
|
||||||
// = 1 + (x * x) / 2 + o(x^4)
|
// = 1 + (x * x) / 2 + o(x^4)
|
||||||
fn cosh32(x: f32) -> f32 {
|
fn cosh32(x: f32) f32 {
|
||||||
const u = @bitCast(u32, x);
|
const u = @bitCast(u32, x);
|
||||||
const ux = u & 0x7FFFFFFF;
|
const ux = u & 0x7FFFFFFF;
|
||||||
const ax = @bitCast(f32, ux);
|
const ax = @bitCast(f32, ux);
|
||||||
@ -47,7 +47,7 @@ fn cosh32(x: f32) -> f32 {
|
|||||||
return expo2(ax);
|
return expo2(ax);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cosh64(x: f64) -> f64 {
|
fn cosh64(x: f64) f64 {
|
||||||
const u = @bitCast(u64, x);
|
const u = @bitCast(u64, x);
|
||||||
const w = u32(u >> 32);
|
const w = u32(u >> 32);
|
||||||
const ax = @bitCast(f64, u & (@maxValue(u64) >> 1));
|
const ax = @bitCast(f64, u & (@maxValue(u64) >> 1));
|
||||||
|
@ -7,7 +7,7 @@ const std = @import("../index.zig");
|
|||||||
const math = std.math;
|
const math = std.math;
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
|
|
||||||
pub fn exp(x: var) -> @typeOf(x) {
|
pub fn exp(x: var) @typeOf(x) {
|
||||||
const T = @typeOf(x);
|
const T = @typeOf(x);
|
||||||
return switch (T) {
|
return switch (T) {
|
||||||
f32 => exp32(x),
|
f32 => exp32(x),
|
||||||
@ -16,7 +16,7 @@ pub fn exp(x: var) -> @typeOf(x) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn exp32(x_: f32) -> f32 {
|
fn exp32(x_: f32) f32 {
|
||||||
const half = []f32 { 0.5, -0.5 };
|
const half = []f32 { 0.5, -0.5 };
|
||||||
const ln2hi = 6.9314575195e-1;
|
const ln2hi = 6.9314575195e-1;
|
||||||
const ln2lo = 1.4286067653e-6;
|
const ln2lo = 1.4286067653e-6;
|
||||||
@ -93,7 +93,7 @@ fn exp32(x_: f32) -> f32 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn exp64(x_: f64) -> f64 {
|
fn exp64(x_: f64) f64 {
|
||||||
const half = []const f64 { 0.5, -0.5 };
|
const half = []const f64 { 0.5, -0.5 };
|
||||||
const ln2hi: f64 = 6.93147180369123816490e-01;
|
const ln2hi: f64 = 6.93147180369123816490e-01;
|
||||||
const ln2lo: f64 = 1.90821492927058770002e-10;
|
const ln2lo: f64 = 1.90821492927058770002e-10;
|
||||||
|
@ -7,7 +7,7 @@ const std = @import("../index.zig");
|
|||||||
const math = std.math;
|
const math = std.math;
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
|
|
||||||
pub fn exp2(x: var) -> @typeOf(x) {
|
pub fn exp2(x: var) @typeOf(x) {
|
||||||
const T = @typeOf(x);
|
const T = @typeOf(x);
|
||||||
return switch (T) {
|
return switch (T) {
|
||||||
f32 => exp2_32(x),
|
f32 => exp2_32(x),
|
||||||
@ -35,7 +35,7 @@ const exp2ft = []const f64 {
|
|||||||
0x1.5ab07dd485429p+0,
|
0x1.5ab07dd485429p+0,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn exp2_32(x: f32) -> f32 {
|
fn exp2_32(x: f32) f32 {
|
||||||
@setFloatMode(this, @import("builtin").FloatMode.Strict);
|
@setFloatMode(this, @import("builtin").FloatMode.Strict);
|
||||||
|
|
||||||
const tblsiz = u32(exp2ft.len);
|
const tblsiz = u32(exp2ft.len);
|
||||||
@ -352,7 +352,7 @@ const exp2dt = []f64 {
|
|||||||
0x1.690f4b19e9471p+0, -0x1.9780p-45,
|
0x1.690f4b19e9471p+0, -0x1.9780p-45,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn exp2_64(x: f64) -> f64 {
|
fn exp2_64(x: f64) f64 {
|
||||||
@setFloatMode(this, @import("builtin").FloatMode.Strict);
|
@setFloatMode(this, @import("builtin").FloatMode.Strict);
|
||||||
|
|
||||||
const tblsiz = u32(exp2dt.len / 2);
|
const tblsiz = u32(exp2dt.len / 2);
|
||||||
|
@ -9,7 +9,7 @@ const std = @import("../index.zig");
|
|||||||
const math = std.math;
|
const math = std.math;
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
|
|
||||||
pub fn expm1(x: var) -> @typeOf(x) {
|
pub fn expm1(x: var) @typeOf(x) {
|
||||||
const T = @typeOf(x);
|
const T = @typeOf(x);
|
||||||
return switch (T) {
|
return switch (T) {
|
||||||
f32 => expm1_32(x),
|
f32 => expm1_32(x),
|
||||||
@ -18,7 +18,7 @@ pub fn expm1(x: var) -> @typeOf(x) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expm1_32(x_: f32) -> f32 {
|
fn expm1_32(x_: f32) f32 {
|
||||||
@setFloatMode(this, builtin.FloatMode.Strict);
|
@setFloatMode(this, builtin.FloatMode.Strict);
|
||||||
const o_threshold: f32 = 8.8721679688e+01;
|
const o_threshold: f32 = 8.8721679688e+01;
|
||||||
const ln2_hi: f32 = 6.9313812256e-01;
|
const ln2_hi: f32 = 6.9313812256e-01;
|
||||||
@ -145,7 +145,7 @@ fn expm1_32(x_: f32) -> f32 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expm1_64(x_: f64) -> f64 {
|
fn expm1_64(x_: f64) f64 {
|
||||||
@setFloatMode(this, builtin.FloatMode.Strict);
|
@setFloatMode(this, builtin.FloatMode.Strict);
|
||||||
const o_threshold: f64 = 7.09782712893383973096e+02;
|
const o_threshold: f64 = 7.09782712893383973096e+02;
|
||||||
const ln2_hi: f64 = 6.93147180369123816490e-01;
|
const ln2_hi: f64 = 6.93147180369123816490e-01;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
const math = @import("index.zig");
|
const math = @import("index.zig");
|
||||||
|
|
||||||
pub fn expo2(x: var) -> @typeOf(x) {
|
pub fn expo2(x: var) @typeOf(x) {
|
||||||
const T = @typeOf(x);
|
const T = @typeOf(x);
|
||||||
return switch (T) {
|
return switch (T) {
|
||||||
f32 => expo2f(x),
|
f32 => expo2f(x),
|
||||||
@ -9,7 +9,7 @@ pub fn expo2(x: var) -> @typeOf(x) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expo2f(x: f32) -> f32 {
|
fn expo2f(x: f32) f32 {
|
||||||
const k: u32 = 235;
|
const k: u32 = 235;
|
||||||
const kln2 = 0x1.45C778p+7;
|
const kln2 = 0x1.45C778p+7;
|
||||||
|
|
||||||
@ -18,7 +18,7 @@ fn expo2f(x: f32) -> f32 {
|
|||||||
return math.exp(x - kln2) * scale * scale;
|
return math.exp(x - kln2) * scale * scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expo2d(x: f64) -> f64 {
|
fn expo2d(x: f64) f64 {
|
||||||
const k: u32 = 2043;
|
const k: u32 = 2043;
|
||||||
const kln2 = 0x1.62066151ADD8BP+10;
|
const kln2 = 0x1.62066151ADD8BP+10;
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ const std = @import("../index.zig");
|
|||||||
const math = std.math;
|
const math = std.math;
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
|
|
||||||
pub fn fabs(x: var) -> @typeOf(x) {
|
pub fn fabs(x: var) @typeOf(x) {
|
||||||
const T = @typeOf(x);
|
const T = @typeOf(x);
|
||||||
return switch (T) {
|
return switch (T) {
|
||||||
f32 => fabs32(x),
|
f32 => fabs32(x),
|
||||||
@ -16,13 +16,13 @@ pub fn fabs(x: var) -> @typeOf(x) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fabs32(x: f32) -> f32 {
|
fn fabs32(x: f32) f32 {
|
||||||
var u = @bitCast(u32, x);
|
var u = @bitCast(u32, x);
|
||||||
u &= 0x7FFFFFFF;
|
u &= 0x7FFFFFFF;
|
||||||
return @bitCast(f32, u);
|
return @bitCast(f32, u);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fabs64(x: f64) -> f64 {
|
fn fabs64(x: f64) f64 {
|
||||||
var u = @bitCast(u64, x);
|
var u = @bitCast(u64, x);
|
||||||
u &= @maxValue(u64) >> 1;
|
u &= @maxValue(u64) >> 1;
|
||||||
return @bitCast(f64, u);
|
return @bitCast(f64, u);
|
||||||
|
@ -9,7 +9,7 @@ const assert = std.debug.assert;
|
|||||||
const std = @import("../index.zig");
|
const std = @import("../index.zig");
|
||||||
const math = std.math;
|
const math = std.math;
|
||||||
|
|
||||||
pub fn floor(x: var) -> @typeOf(x) {
|
pub fn floor(x: var) @typeOf(x) {
|
||||||
const T = @typeOf(x);
|
const T = @typeOf(x);
|
||||||
return switch (T) {
|
return switch (T) {
|
||||||
f32 => floor32(x),
|
f32 => floor32(x),
|
||||||
@ -18,7 +18,7 @@ pub fn floor(x: var) -> @typeOf(x) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn floor32(x: f32) -> f32 {
|
fn floor32(x: f32) f32 {
|
||||||
var u = @bitCast(u32, x);
|
var u = @bitCast(u32, x);
|
||||||
const e = i32((u >> 23) & 0xFF) - 0x7F;
|
const e = i32((u >> 23) & 0xFF) - 0x7F;
|
||||||
var m: u32 = undefined;
|
var m: u32 = undefined;
|
||||||
@ -52,7 +52,7 @@ fn floor32(x: f32) -> f32 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn floor64(x: f64) -> f64 {
|
fn floor64(x: f64) f64 {
|
||||||
const u = @bitCast(u64, x);
|
const u = @bitCast(u64, x);
|
||||||
const e = (u >> 52) & 0x7FF;
|
const e = (u >> 52) & 0x7FF;
|
||||||
var y: f64 = undefined;
|
var y: f64 = undefined;
|
||||||
|
@ -2,7 +2,7 @@ const std = @import("../index.zig");
|
|||||||
const math = std.math;
|
const math = std.math;
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
|
|
||||||
pub fn fma(comptime T: type, x: T, y: T, z: T) -> T {
|
pub fn fma(comptime T: type, x: T, y: T, z: T) T {
|
||||||
return switch (T) {
|
return switch (T) {
|
||||||
f32 => fma32(x, y, z),
|
f32 => fma32(x, y, z),
|
||||||
f64 => fma64(x, y ,z),
|
f64 => fma64(x, y ,z),
|
||||||
@ -10,7 +10,7 @@ pub fn fma(comptime T: type, x: T, y: T, z: T) -> T {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fma32(x: f32, y: f32, z: f32) -> f32 {
|
fn fma32(x: f32, y: f32, z: f32) f32 {
|
||||||
const xy = f64(x) * y;
|
const xy = f64(x) * y;
|
||||||
const xy_z = xy + z;
|
const xy_z = xy + z;
|
||||||
const u = @bitCast(u64, xy_z);
|
const u = @bitCast(u64, xy_z);
|
||||||
@ -24,7 +24,7 @@ fn fma32(x: f32, y: f32, z: f32) -> f32 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fma64(x: f64, y: f64, z: f64) -> f64 {
|
fn fma64(x: f64, y: f64, z: f64) f64 {
|
||||||
if (!math.isFinite(x) or !math.isFinite(y)) {
|
if (!math.isFinite(x) or !math.isFinite(y)) {
|
||||||
return x * y + z;
|
return x * y + z;
|
||||||
}
|
}
|
||||||
@ -73,7 +73,7 @@ fn fma64(x: f64, y: f64, z: f64) -> f64 {
|
|||||||
|
|
||||||
const dd = struct { hi: f64, lo: f64, };
|
const dd = struct { hi: f64, lo: f64, };
|
||||||
|
|
||||||
fn dd_add(a: f64, b: f64) -> dd {
|
fn dd_add(a: f64, b: f64) dd {
|
||||||
var ret: dd = undefined;
|
var ret: dd = undefined;
|
||||||
ret.hi = a + b;
|
ret.hi = a + b;
|
||||||
const s = ret.hi - a;
|
const s = ret.hi - a;
|
||||||
@ -81,7 +81,7 @@ fn dd_add(a: f64, b: f64) -> dd {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dd_mul(a: f64, b: f64) -> dd {
|
fn dd_mul(a: f64, b: f64) dd {
|
||||||
var ret: dd = undefined;
|
var ret: dd = undefined;
|
||||||
const split: f64 = 0x1.0p27 + 1.0;
|
const split: f64 = 0x1.0p27 + 1.0;
|
||||||
|
|
||||||
@ -103,7 +103,7 @@ fn dd_mul(a: f64, b: f64) -> dd {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_adjusted(a: f64, b: f64) -> f64 {
|
fn add_adjusted(a: f64, b: f64) f64 {
|
||||||
var sum = dd_add(a, b);
|
var sum = dd_add(a, b);
|
||||||
if (sum.lo != 0) {
|
if (sum.lo != 0) {
|
||||||
var uhii = @bitCast(u64, sum.hi);
|
var uhii = @bitCast(u64, sum.hi);
|
||||||
@ -117,7 +117,7 @@ fn add_adjusted(a: f64, b: f64) -> f64 {
|
|||||||
return sum.hi;
|
return sum.hi;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_and_denorm(a: f64, b: f64, scale: i32) -> f64 {
|
fn add_and_denorm(a: f64, b: f64, scale: i32) f64 {
|
||||||
var sum = dd_add(a, b);
|
var sum = dd_add(a, b);
|
||||||
if (sum.lo != 0) {
|
if (sum.lo != 0) {
|
||||||
var uhii = @bitCast(u64, sum.hi);
|
var uhii = @bitCast(u64, sum.hi);
|
||||||
|
@ -8,7 +8,7 @@ const std = @import("../index.zig");
|
|||||||
const math = std.math;
|
const math = std.math;
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
|
|
||||||
fn frexp_result(comptime T: type) -> type {
|
fn frexp_result(comptime T: type) type {
|
||||||
return struct {
|
return struct {
|
||||||
significand: T,
|
significand: T,
|
||||||
exponent: i32,
|
exponent: i32,
|
||||||
@ -17,7 +17,7 @@ fn frexp_result(comptime T: type) -> type {
|
|||||||
pub const frexp32_result = frexp_result(f32);
|
pub const frexp32_result = frexp_result(f32);
|
||||||
pub const frexp64_result = frexp_result(f64);
|
pub const frexp64_result = frexp_result(f64);
|
||||||
|
|
||||||
pub fn frexp(x: var) -> frexp_result(@typeOf(x)) {
|
pub fn frexp(x: var) frexp_result(@typeOf(x)) {
|
||||||
const T = @typeOf(x);
|
const T = @typeOf(x);
|
||||||
return switch (T) {
|
return switch (T) {
|
||||||
f32 => frexp32(x),
|
f32 => frexp32(x),
|
||||||
@ -26,7 +26,7 @@ pub fn frexp(x: var) -> frexp_result(@typeOf(x)) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn frexp32(x: f32) -> frexp32_result {
|
fn frexp32(x: f32) frexp32_result {
|
||||||
var result: frexp32_result = undefined;
|
var result: frexp32_result = undefined;
|
||||||
|
|
||||||
var y = @bitCast(u32, x);
|
var y = @bitCast(u32, x);
|
||||||
@ -63,7 +63,7 @@ fn frexp32(x: f32) -> frexp32_result {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn frexp64(x: f64) -> frexp64_result {
|
fn frexp64(x: f64) frexp64_result {
|
||||||
var result: frexp64_result = undefined;
|
var result: frexp64_result = undefined;
|
||||||
|
|
||||||
var y = @bitCast(u64, x);
|
var y = @bitCast(u64, x);
|
||||||
|
@ -9,7 +9,7 @@ const std = @import("../index.zig");
|
|||||||
const math = std.math;
|
const math = std.math;
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
|
|
||||||
pub fn hypot(comptime T: type, x: T, y: T) -> T {
|
pub fn hypot(comptime T: type, x: T, y: T) T {
|
||||||
return switch (T) {
|
return switch (T) {
|
||||||
f32 => hypot32(x, y),
|
f32 => hypot32(x, y),
|
||||||
f64 => hypot64(x, y),
|
f64 => hypot64(x, y),
|
||||||
@ -17,7 +17,7 @@ pub fn hypot(comptime T: type, x: T, y: T) -> T {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hypot32(x: f32, y: f32) -> f32 {
|
fn hypot32(x: f32, y: f32) f32 {
|
||||||
var ux = @bitCast(u32, x);
|
var ux = @bitCast(u32, x);
|
||||||
var uy = @bitCast(u32, y);
|
var uy = @bitCast(u32, y);
|
||||||
|
|
||||||
@ -52,7 +52,7 @@ fn hypot32(x: f32, y: f32) -> f32 {
|
|||||||
return z * math.sqrt(f32(f64(x) * x + f64(y) * y));
|
return z * math.sqrt(f32(f64(x) * x + f64(y) * y));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sq(hi: &f64, lo: &f64, x: f64) {
|
fn sq(hi: &f64, lo: &f64, x: f64) void {
|
||||||
const split: f64 = 0x1.0p27 + 1.0;
|
const split: f64 = 0x1.0p27 + 1.0;
|
||||||
const xc = x * split;
|
const xc = x * split;
|
||||||
const xh = x - xc + xc;
|
const xh = x - xc + xc;
|
||||||
@ -61,7 +61,7 @@ fn sq(hi: &f64, lo: &f64, x: f64) {
|
|||||||
*lo = xh * xh - *hi + 2 * xh * xl + xl * xl;
|
*lo = xh * xh - *hi + 2 * xh * xl + xl * xl;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hypot64(x: f64, y: f64) -> f64 {
|
fn hypot64(x: f64, y: f64) f64 {
|
||||||
var ux = @bitCast(u64, x);
|
var ux = @bitCast(u64, x);
|
||||||
var uy = @bitCast(u64, y);
|
var uy = @bitCast(u64, y);
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ const std = @import("../index.zig");
|
|||||||
const math = std.math;
|
const math = std.math;
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
|
|
||||||
pub fn ilogb(x: var) -> i32 {
|
pub fn ilogb(x: var) i32 {
|
||||||
const T = @typeOf(x);
|
const T = @typeOf(x);
|
||||||
return switch (T) {
|
return switch (T) {
|
||||||
f32 => ilogb32(x),
|
f32 => ilogb32(x),
|
||||||
@ -21,7 +21,7 @@ pub fn ilogb(x: var) -> i32 {
|
|||||||
const fp_ilogbnan = -1 - i32(@maxValue(u32) >> 1);
|
const fp_ilogbnan = -1 - i32(@maxValue(u32) >> 1);
|
||||||
const fp_ilogb0 = fp_ilogbnan;
|
const fp_ilogb0 = fp_ilogbnan;
|
||||||
|
|
||||||
fn ilogb32(x: f32) -> i32 {
|
fn ilogb32(x: f32) i32 {
|
||||||
var u = @bitCast(u32, x);
|
var u = @bitCast(u32, x);
|
||||||
var e = i32((u >> 23) & 0xFF);
|
var e = i32((u >> 23) & 0xFF);
|
||||||
|
|
||||||
@ -57,7 +57,7 @@ fn ilogb32(x: f32) -> i32 {
|
|||||||
return e - 0x7F;
|
return e - 0x7F;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ilogb64(x: f64) -> i32 {
|
fn ilogb64(x: f64) i32 {
|
||||||
var u = @bitCast(u64, x);
|
var u = @bitCast(u64, x);
|
||||||
var e = i32((u >> 52) & 0x7FF);
|
var e = i32((u >> 52) & 0x7FF);
|
||||||
|
|
||||||
|
@ -35,13 +35,13 @@ pub const nan = @import("nan.zig").nan;
|
|||||||
pub const snan = @import("nan.zig").snan;
|
pub const snan = @import("nan.zig").snan;
|
||||||
pub const inf = @import("inf.zig").inf;
|
pub const inf = @import("inf.zig").inf;
|
||||||
|
|
||||||
pub fn approxEq(comptime T: type, x: T, y: T, epsilon: T) -> bool {
|
pub fn approxEq(comptime T: type, x: T, y: T, epsilon: T) bool {
|
||||||
assert(@typeId(T) == TypeId.Float);
|
assert(@typeId(T) == TypeId.Float);
|
||||||
return fabs(x - y) < epsilon;
|
return fabs(x - y) < epsilon;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Hide the following in an internal module.
|
// TODO: Hide the following in an internal module.
|
||||||
pub fn forceEval(value: var) {
|
pub fn forceEval(value: var) void {
|
||||||
const T = @typeOf(value);
|
const T = @typeOf(value);
|
||||||
switch (T) {
|
switch (T) {
|
||||||
f32 => {
|
f32 => {
|
||||||
@ -60,23 +60,23 @@ pub fn forceEval(value: var) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn raiseInvalid() {
|
pub fn raiseInvalid() void {
|
||||||
// Raise INVALID fpu exception
|
// Raise INVALID fpu exception
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn raiseUnderflow() {
|
pub fn raiseUnderflow() void {
|
||||||
// Raise UNDERFLOW fpu exception
|
// Raise UNDERFLOW fpu exception
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn raiseOverflow() {
|
pub fn raiseOverflow() void {
|
||||||
// Raise OVERFLOW fpu exception
|
// Raise OVERFLOW fpu exception
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn raiseInexact() {
|
pub fn raiseInexact() void {
|
||||||
// Raise INEXACT fpu exception
|
// Raise INEXACT fpu exception
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn raiseDivByZero() {
|
pub fn raiseDivByZero() void {
|
||||||
// Raise INEXACT fpu exception
|
// Raise INEXACT fpu exception
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,7 +175,7 @@ test "math" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn min(x: var, y: var) -> @typeOf(x + y) {
|
pub fn min(x: var, y: var) @typeOf(x + y) {
|
||||||
return if (x < y) x else y;
|
return if (x < y) x else y;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,7 +183,7 @@ test "math.min" {
|
|||||||
assert(min(i32(-1), i32(2)) == -1);
|
assert(min(i32(-1), i32(2)) == -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn max(x: var, y: var) -> @typeOf(x + y) {
|
pub fn max(x: var, y: var) @typeOf(x + y) {
|
||||||
return if (x > y) x else y;
|
return if (x > y) x else y;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,36 +192,36 @@ test "math.max" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
error Overflow;
|
error Overflow;
|
||||||
pub fn mul(comptime T: type, a: T, b: T) -> %T {
|
pub fn mul(comptime T: type, a: T, b: T) %T {
|
||||||
var answer: T = undefined;
|
var answer: T = undefined;
|
||||||
return if (@mulWithOverflow(T, a, b, &answer)) error.Overflow else answer;
|
return if (@mulWithOverflow(T, a, b, &answer)) error.Overflow else answer;
|
||||||
}
|
}
|
||||||
|
|
||||||
error Overflow;
|
error Overflow;
|
||||||
pub fn add(comptime T: type, a: T, b: T) -> %T {
|
pub fn add(comptime T: type, a: T, b: T) %T {
|
||||||
var answer: T = undefined;
|
var answer: T = undefined;
|
||||||
return if (@addWithOverflow(T, a, b, &answer)) error.Overflow else answer;
|
return if (@addWithOverflow(T, a, b, &answer)) error.Overflow else answer;
|
||||||
}
|
}
|
||||||
|
|
||||||
error Overflow;
|
error Overflow;
|
||||||
pub fn sub(comptime T: type, a: T, b: T) -> %T {
|
pub fn sub(comptime T: type, a: T, b: T) %T {
|
||||||
var answer: T = undefined;
|
var answer: T = undefined;
|
||||||
return if (@subWithOverflow(T, a, b, &answer)) error.Overflow else answer;
|
return if (@subWithOverflow(T, a, b, &answer)) error.Overflow else answer;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn negate(x: var) -> %@typeOf(x) {
|
pub fn negate(x: var) %@typeOf(x) {
|
||||||
return sub(@typeOf(x), 0, x);
|
return sub(@typeOf(x), 0, x);
|
||||||
}
|
}
|
||||||
|
|
||||||
error Overflow;
|
error Overflow;
|
||||||
pub fn shlExact(comptime T: type, a: T, shift_amt: Log2Int(T)) -> %T {
|
pub fn shlExact(comptime T: type, a: T, shift_amt: Log2Int(T)) %T {
|
||||||
var answer: T = undefined;
|
var answer: T = undefined;
|
||||||
return if (@shlWithOverflow(T, a, shift_amt, &answer)) error.Overflow else answer;
|
return if (@shlWithOverflow(T, a, shift_amt, &answer)) error.Overflow else answer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Shifts left. Overflowed bits are truncated.
|
/// Shifts left. Overflowed bits are truncated.
|
||||||
/// A negative shift amount results in a right shift.
|
/// A negative shift amount results in a right shift.
|
||||||
pub fn shl(comptime T: type, a: T, shift_amt: var) -> T {
|
pub fn shl(comptime T: type, a: T, shift_amt: var) T {
|
||||||
const abs_shift_amt = absCast(shift_amt);
|
const abs_shift_amt = absCast(shift_amt);
|
||||||
const casted_shift_amt = if (abs_shift_amt >= T.bit_count) return 0 else Log2Int(T)(abs_shift_amt);
|
const casted_shift_amt = if (abs_shift_amt >= T.bit_count) return 0 else Log2Int(T)(abs_shift_amt);
|
||||||
|
|
||||||
@ -245,7 +245,7 @@ test "math.shl" {
|
|||||||
|
|
||||||
/// Shifts right. Overflowed bits are truncated.
|
/// Shifts right. Overflowed bits are truncated.
|
||||||
/// A negative shift amount results in a lefft shift.
|
/// A negative shift amount results in a lefft shift.
|
||||||
pub fn shr(comptime T: type, a: T, shift_amt: var) -> T {
|
pub fn shr(comptime T: type, a: T, shift_amt: var) T {
|
||||||
const abs_shift_amt = absCast(shift_amt);
|
const abs_shift_amt = absCast(shift_amt);
|
||||||
const casted_shift_amt = if (abs_shift_amt >= T.bit_count) return 0 else Log2Int(T)(abs_shift_amt);
|
const casted_shift_amt = if (abs_shift_amt >= T.bit_count) return 0 else Log2Int(T)(abs_shift_amt);
|
||||||
|
|
||||||
@ -269,7 +269,7 @@ test "math.shr" {
|
|||||||
|
|
||||||
/// Rotates right. Only unsigned values can be rotated.
|
/// Rotates right. Only unsigned values can be rotated.
|
||||||
/// Negative shift values results in shift modulo the bit count.
|
/// Negative shift values results in shift modulo the bit count.
|
||||||
pub fn rotr(comptime T: type, x: T, r: var) -> T {
|
pub fn rotr(comptime T: type, x: T, r: var) T {
|
||||||
if (T.is_signed) {
|
if (T.is_signed) {
|
||||||
@compileError("cannot rotate signed integer");
|
@compileError("cannot rotate signed integer");
|
||||||
} else {
|
} else {
|
||||||
@ -288,7 +288,7 @@ test "math.rotr" {
|
|||||||
|
|
||||||
/// Rotates left. Only unsigned values can be rotated.
|
/// Rotates left. Only unsigned values can be rotated.
|
||||||
/// Negative shift values results in shift modulo the bit count.
|
/// Negative shift values results in shift modulo the bit count.
|
||||||
pub fn rotl(comptime T: type, x: T, r: var) -> T {
|
pub fn rotl(comptime T: type, x: T, r: var) T {
|
||||||
if (T.is_signed) {
|
if (T.is_signed) {
|
||||||
@compileError("cannot rotate signed integer");
|
@compileError("cannot rotate signed integer");
|
||||||
} else {
|
} else {
|
||||||
@ -306,7 +306,7 @@ test "math.rotl" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn Log2Int(comptime T: type) -> type {
|
pub fn Log2Int(comptime T: type) type {
|
||||||
return @IntType(false, log2(T.bit_count));
|
return @IntType(false, log2(T.bit_count));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -315,7 +315,7 @@ test "math overflow functions" {
|
|||||||
comptime testOverflow();
|
comptime testOverflow();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn testOverflow() {
|
fn testOverflow() void {
|
||||||
assert((mul(i32, 3, 4) catch unreachable) == 12);
|
assert((mul(i32, 3, 4) catch unreachable) == 12);
|
||||||
assert((add(i32, 3, 4) catch unreachable) == 7);
|
assert((add(i32, 3, 4) catch unreachable) == 7);
|
||||||
assert((sub(i32, 3, 4) catch unreachable) == -1);
|
assert((sub(i32, 3, 4) catch unreachable) == -1);
|
||||||
@ -324,7 +324,7 @@ fn testOverflow() {
|
|||||||
|
|
||||||
|
|
||||||
error Overflow;
|
error Overflow;
|
||||||
pub fn absInt(x: var) -> %@typeOf(x) {
|
pub fn absInt(x: var) %@typeOf(x) {
|
||||||
const T = @typeOf(x);
|
const T = @typeOf(x);
|
||||||
comptime assert(@typeId(T) == builtin.TypeId.Int); // must pass an integer to absInt
|
comptime assert(@typeId(T) == builtin.TypeId.Int); // must pass an integer to absInt
|
||||||
comptime assert(T.is_signed); // must pass a signed integer to absInt
|
comptime assert(T.is_signed); // must pass a signed integer to absInt
|
||||||
@ -340,7 +340,7 @@ test "math.absInt" {
|
|||||||
testAbsInt();
|
testAbsInt();
|
||||||
comptime testAbsInt();
|
comptime testAbsInt();
|
||||||
}
|
}
|
||||||
fn testAbsInt() {
|
fn testAbsInt() void {
|
||||||
assert((absInt(i32(-10)) catch unreachable) == 10);
|
assert((absInt(i32(-10)) catch unreachable) == 10);
|
||||||
assert((absInt(i32(10)) catch unreachable) == 10);
|
assert((absInt(i32(10)) catch unreachable) == 10);
|
||||||
}
|
}
|
||||||
@ -349,7 +349,7 @@ pub const absFloat = @import("fabs.zig").fabs;
|
|||||||
|
|
||||||
error DivisionByZero;
|
error DivisionByZero;
|
||||||
error Overflow;
|
error Overflow;
|
||||||
pub fn divTrunc(comptime T: type, numerator: T, denominator: T) -> %T {
|
pub fn divTrunc(comptime T: type, numerator: T, denominator: T) %T {
|
||||||
@setRuntimeSafety(false);
|
@setRuntimeSafety(false);
|
||||||
if (denominator == 0)
|
if (denominator == 0)
|
||||||
return error.DivisionByZero;
|
return error.DivisionByZero;
|
||||||
@ -362,7 +362,7 @@ test "math.divTrunc" {
|
|||||||
testDivTrunc();
|
testDivTrunc();
|
||||||
comptime testDivTrunc();
|
comptime testDivTrunc();
|
||||||
}
|
}
|
||||||
fn testDivTrunc() {
|
fn testDivTrunc() void {
|
||||||
assert((divTrunc(i32, 5, 3) catch unreachable) == 1);
|
assert((divTrunc(i32, 5, 3) catch unreachable) == 1);
|
||||||
assert((divTrunc(i32, -5, 3) catch unreachable) == -1);
|
assert((divTrunc(i32, -5, 3) catch unreachable) == -1);
|
||||||
if (divTrunc(i8, -5, 0)) |_| unreachable else |err| assert(err == error.DivisionByZero);
|
if (divTrunc(i8, -5, 0)) |_| unreachable else |err| assert(err == error.DivisionByZero);
|
||||||
@ -374,7 +374,7 @@ fn testDivTrunc() {
|
|||||||
|
|
||||||
error DivisionByZero;
|
error DivisionByZero;
|
||||||
error Overflow;
|
error Overflow;
|
||||||
pub fn divFloor(comptime T: type, numerator: T, denominator: T) -> %T {
|
pub fn divFloor(comptime T: type, numerator: T, denominator: T) %T {
|
||||||
@setRuntimeSafety(false);
|
@setRuntimeSafety(false);
|
||||||
if (denominator == 0)
|
if (denominator == 0)
|
||||||
return error.DivisionByZero;
|
return error.DivisionByZero;
|
||||||
@ -387,7 +387,7 @@ test "math.divFloor" {
|
|||||||
testDivFloor();
|
testDivFloor();
|
||||||
comptime testDivFloor();
|
comptime testDivFloor();
|
||||||
}
|
}
|
||||||
fn testDivFloor() {
|
fn testDivFloor() void {
|
||||||
assert((divFloor(i32, 5, 3) catch unreachable) == 1);
|
assert((divFloor(i32, 5, 3) catch unreachable) == 1);
|
||||||
assert((divFloor(i32, -5, 3) catch unreachable) == -2);
|
assert((divFloor(i32, -5, 3) catch unreachable) == -2);
|
||||||
if (divFloor(i8, -5, 0)) |_| unreachable else |err| assert(err == error.DivisionByZero);
|
if (divFloor(i8, -5, 0)) |_| unreachable else |err| assert(err == error.DivisionByZero);
|
||||||
@ -400,7 +400,7 @@ fn testDivFloor() {
|
|||||||
error DivisionByZero;
|
error DivisionByZero;
|
||||||
error Overflow;
|
error Overflow;
|
||||||
error UnexpectedRemainder;
|
error UnexpectedRemainder;
|
||||||
pub fn divExact(comptime T: type, numerator: T, denominator: T) -> %T {
|
pub fn divExact(comptime T: type, numerator: T, denominator: T) %T {
|
||||||
@setRuntimeSafety(false);
|
@setRuntimeSafety(false);
|
||||||
if (denominator == 0)
|
if (denominator == 0)
|
||||||
return error.DivisionByZero;
|
return error.DivisionByZero;
|
||||||
@ -416,7 +416,7 @@ test "math.divExact" {
|
|||||||
testDivExact();
|
testDivExact();
|
||||||
comptime testDivExact();
|
comptime testDivExact();
|
||||||
}
|
}
|
||||||
fn testDivExact() {
|
fn testDivExact() void {
|
||||||
assert((divExact(i32, 10, 5) catch unreachable) == 2);
|
assert((divExact(i32, 10, 5) catch unreachable) == 2);
|
||||||
assert((divExact(i32, -10, 5) catch unreachable) == -2);
|
assert((divExact(i32, -10, 5) catch unreachable) == -2);
|
||||||
if (divExact(i8, -5, 0)) |_| unreachable else |err| assert(err == error.DivisionByZero);
|
if (divExact(i8, -5, 0)) |_| unreachable else |err| assert(err == error.DivisionByZero);
|
||||||
@ -430,7 +430,7 @@ fn testDivExact() {
|
|||||||
|
|
||||||
error DivisionByZero;
|
error DivisionByZero;
|
||||||
error NegativeDenominator;
|
error NegativeDenominator;
|
||||||
pub fn mod(comptime T: type, numerator: T, denominator: T) -> %T {
|
pub fn mod(comptime T: type, numerator: T, denominator: T) %T {
|
||||||
@setRuntimeSafety(false);
|
@setRuntimeSafety(false);
|
||||||
if (denominator == 0)
|
if (denominator == 0)
|
||||||
return error.DivisionByZero;
|
return error.DivisionByZero;
|
||||||
@ -443,7 +443,7 @@ test "math.mod" {
|
|||||||
testMod();
|
testMod();
|
||||||
comptime testMod();
|
comptime testMod();
|
||||||
}
|
}
|
||||||
fn testMod() {
|
fn testMod() void {
|
||||||
assert((mod(i32, -5, 3) catch unreachable) == 1);
|
assert((mod(i32, -5, 3) catch unreachable) == 1);
|
||||||
assert((mod(i32, 5, 3) catch unreachable) == 2);
|
assert((mod(i32, 5, 3) catch unreachable) == 2);
|
||||||
if (mod(i32, 10, -1)) |_| unreachable else |err| assert(err == error.NegativeDenominator);
|
if (mod(i32, 10, -1)) |_| unreachable else |err| assert(err == error.NegativeDenominator);
|
||||||
@ -457,7 +457,7 @@ fn testMod() {
|
|||||||
|
|
||||||
error DivisionByZero;
|
error DivisionByZero;
|
||||||
error NegativeDenominator;
|
error NegativeDenominator;
|
||||||
pub fn rem(comptime T: type, numerator: T, denominator: T) -> %T {
|
pub fn rem(comptime T: type, numerator: T, denominator: T) %T {
|
||||||
@setRuntimeSafety(false);
|
@setRuntimeSafety(false);
|
||||||
if (denominator == 0)
|
if (denominator == 0)
|
||||||
return error.DivisionByZero;
|
return error.DivisionByZero;
|
||||||
@ -470,7 +470,7 @@ test "math.rem" {
|
|||||||
testRem();
|
testRem();
|
||||||
comptime testRem();
|
comptime testRem();
|
||||||
}
|
}
|
||||||
fn testRem() {
|
fn testRem() void {
|
||||||
assert((rem(i32, -5, 3) catch unreachable) == -2);
|
assert((rem(i32, -5, 3) catch unreachable) == -2);
|
||||||
assert((rem(i32, 5, 3) catch unreachable) == 2);
|
assert((rem(i32, 5, 3) catch unreachable) == 2);
|
||||||
if (rem(i32, 10, -1)) |_| unreachable else |err| assert(err == error.NegativeDenominator);
|
if (rem(i32, 10, -1)) |_| unreachable else |err| assert(err == error.NegativeDenominator);
|
||||||
@ -484,7 +484,7 @@ fn testRem() {
|
|||||||
|
|
||||||
/// Returns the absolute value of the integer parameter.
|
/// Returns the absolute value of the integer parameter.
|
||||||
/// Result is an unsigned integer.
|
/// Result is an unsigned integer.
|
||||||
pub fn absCast(x: var) -> @IntType(false, @typeOf(x).bit_count) {
|
pub fn absCast(x: var) @IntType(false, @typeOf(x).bit_count) {
|
||||||
const uint = @IntType(false, @typeOf(x).bit_count);
|
const uint = @IntType(false, @typeOf(x).bit_count);
|
||||||
if (x >= 0)
|
if (x >= 0)
|
||||||
return uint(x);
|
return uint(x);
|
||||||
@ -506,7 +506,7 @@ test "math.absCast" {
|
|||||||
/// Returns the negation of the integer parameter.
|
/// Returns the negation of the integer parameter.
|
||||||
/// Result is a signed integer.
|
/// Result is a signed integer.
|
||||||
error Overflow;
|
error Overflow;
|
||||||
pub fn negateCast(x: var) -> %@IntType(true, @typeOf(x).bit_count) {
|
pub fn negateCast(x: var) %@IntType(true, @typeOf(x).bit_count) {
|
||||||
if (@typeOf(x).is_signed)
|
if (@typeOf(x).is_signed)
|
||||||
return negate(x);
|
return negate(x);
|
||||||
|
|
||||||
@ -533,7 +533,7 @@ test "math.negateCast" {
|
|||||||
/// Cast an integer to a different integer type. If the value doesn't fit,
|
/// Cast an integer to a different integer type. If the value doesn't fit,
|
||||||
/// return an error.
|
/// return an error.
|
||||||
error Overflow;
|
error Overflow;
|
||||||
pub fn cast(comptime T: type, x: var) -> %T {
|
pub fn cast(comptime T: type, x: var) %T {
|
||||||
comptime assert(@typeId(T) == builtin.TypeId.Int); // must pass an integer
|
comptime assert(@typeId(T) == builtin.TypeId.Int); // must pass an integer
|
||||||
if (x > @maxValue(T)) {
|
if (x > @maxValue(T)) {
|
||||||
return error.Overflow;
|
return error.Overflow;
|
||||||
@ -542,7 +542,7 @@ pub fn cast(comptime T: type, x: var) -> %T {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn floorPowerOfTwo(comptime T: type, value: T) -> T {
|
pub fn floorPowerOfTwo(comptime T: type, value: T) T {
|
||||||
var x = value;
|
var x = value;
|
||||||
|
|
||||||
comptime var i = 1;
|
comptime var i = 1;
|
||||||
@ -558,7 +558,7 @@ test "math.floorPowerOfTwo" {
|
|||||||
comptime testFloorPowerOfTwo();
|
comptime testFloorPowerOfTwo();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn testFloorPowerOfTwo() {
|
fn testFloorPowerOfTwo() void {
|
||||||
assert(floorPowerOfTwo(u32, 63) == 32);
|
assert(floorPowerOfTwo(u32, 63) == 32);
|
||||||
assert(floorPowerOfTwo(u32, 64) == 64);
|
assert(floorPowerOfTwo(u32, 64) == 64);
|
||||||
assert(floorPowerOfTwo(u32, 65) == 64);
|
assert(floorPowerOfTwo(u32, 65) == 64);
|
||||||
|
@ -2,7 +2,7 @@ const std = @import("../index.zig");
|
|||||||
const math = std.math;
|
const math = std.math;
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
|
|
||||||
pub fn inf(comptime T: type) -> T {
|
pub fn inf(comptime T: type) T {
|
||||||
return switch (T) {
|
return switch (T) {
|
||||||
f32 => @bitCast(f32, math.inf_u32),
|
f32 => @bitCast(f32, math.inf_u32),
|
||||||
f64 => @bitCast(f64, math.inf_u64),
|
f64 => @bitCast(f64, math.inf_u64),
|
||||||
|
@ -2,7 +2,7 @@ const std = @import("../index.zig");
|
|||||||
const math = std.math;
|
const math = std.math;
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
|
|
||||||
pub fn isFinite(x: var) -> bool {
|
pub fn isFinite(x: var) bool {
|
||||||
const T = @typeOf(x);
|
const T = @typeOf(x);
|
||||||
switch (T) {
|
switch (T) {
|
||||||
f32 => {
|
f32 => {
|
||||||
|
@ -2,7 +2,7 @@ const std = @import("../index.zig");
|
|||||||
const math = std.math;
|
const math = std.math;
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
|
|
||||||
pub fn isInf(x: var) -> bool {
|
pub fn isInf(x: var) bool {
|
||||||
const T = @typeOf(x);
|
const T = @typeOf(x);
|
||||||
switch (T) {
|
switch (T) {
|
||||||
f32 => {
|
f32 => {
|
||||||
@ -19,7 +19,7 @@ pub fn isInf(x: var) -> bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn isPositiveInf(x: var) -> bool {
|
pub fn isPositiveInf(x: var) bool {
|
||||||
const T = @typeOf(x);
|
const T = @typeOf(x);
|
||||||
switch (T) {
|
switch (T) {
|
||||||
f32 => {
|
f32 => {
|
||||||
@ -34,7 +34,7 @@ pub fn isPositiveInf(x: var) -> bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn isNegativeInf(x: var) -> bool {
|
pub fn isNegativeInf(x: var) bool {
|
||||||
const T = @typeOf(x);
|
const T = @typeOf(x);
|
||||||
switch (T) {
|
switch (T) {
|
||||||
f32 => {
|
f32 => {
|
||||||
|
@ -2,7 +2,7 @@ const std = @import("../index.zig");
|
|||||||
const math = std.math;
|
const math = std.math;
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
|
|
||||||
pub fn isNan(x: var) -> bool {
|
pub fn isNan(x: var) bool {
|
||||||
const T = @typeOf(x);
|
const T = @typeOf(x);
|
||||||
switch (T) {
|
switch (T) {
|
||||||
f32 => {
|
f32 => {
|
||||||
@ -21,7 +21,7 @@ pub fn isNan(x: var) -> bool {
|
|||||||
|
|
||||||
// Note: A signalling nan is identical to a standard right now by may have a different bit
|
// Note: A signalling nan is identical to a standard right now by may have a different bit
|
||||||
// representation in the future when required.
|
// representation in the future when required.
|
||||||
pub fn isSignalNan(x: var) -> bool {
|
pub fn isSignalNan(x: var) bool {
|
||||||
return isNan(x);
|
return isNan(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ const std = @import("../index.zig");
|
|||||||
const math = std.math;
|
const math = std.math;
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
|
|
||||||
pub fn isNormal(x: var) -> bool {
|
pub fn isNormal(x: var) bool {
|
||||||
const T = @typeOf(x);
|
const T = @typeOf(x);
|
||||||
switch (T) {
|
switch (T) {
|
||||||
f32 => {
|
f32 => {
|
||||||
|
@ -11,7 +11,7 @@ const assert = std.debug.assert;
|
|||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
const TypeId = builtin.TypeId;
|
const TypeId = builtin.TypeId;
|
||||||
|
|
||||||
pub fn ln(x: var) -> @typeOf(x) {
|
pub fn ln(x: var) @typeOf(x) {
|
||||||
const T = @typeOf(x);
|
const T = @typeOf(x);
|
||||||
switch (@typeId(T)) {
|
switch (@typeId(T)) {
|
||||||
TypeId.FloatLiteral => {
|
TypeId.FloatLiteral => {
|
||||||
@ -34,7 +34,7 @@ pub fn ln(x: var) -> @typeOf(x) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ln_32(x_: f32) -> f32 {
|
pub fn ln_32(x_: f32) f32 {
|
||||||
@setFloatMode(this, @import("builtin").FloatMode.Strict);
|
@setFloatMode(this, @import("builtin").FloatMode.Strict);
|
||||||
|
|
||||||
const ln2_hi: f32 = 6.9313812256e-01;
|
const ln2_hi: f32 = 6.9313812256e-01;
|
||||||
@ -88,7 +88,7 @@ pub fn ln_32(x_: f32) -> f32 {
|
|||||||
return s * (hfsq + R) + dk * ln2_lo - hfsq + f + dk * ln2_hi;
|
return s * (hfsq + R) + dk * ln2_lo - hfsq + f + dk * ln2_hi;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ln_64(x_: f64) -> f64 {
|
pub fn ln_64(x_: f64) f64 {
|
||||||
const ln2_hi: f64 = 6.93147180369123816490e-01;
|
const ln2_hi: f64 = 6.93147180369123816490e-01;
|
||||||
const ln2_lo: f64 = 1.90821492927058770002e-10;
|
const ln2_lo: f64 = 1.90821492927058770002e-10;
|
||||||
const Lg1: f64 = 6.666666666666735130e-01;
|
const Lg1: f64 = 6.666666666666735130e-01;
|
||||||
|
@ -4,7 +4,7 @@ const builtin = @import("builtin");
|
|||||||
const TypeId = builtin.TypeId;
|
const TypeId = builtin.TypeId;
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
|
|
||||||
pub fn log(comptime T: type, base: T, x: T) -> T {
|
pub fn log(comptime T: type, base: T, x: T) T {
|
||||||
if (base == 2) {
|
if (base == 2) {
|
||||||
return math.log2(x);
|
return math.log2(x);
|
||||||
} else if (base == 10) {
|
} else if (base == 10) {
|
||||||
|
@ -11,7 +11,7 @@ const assert = std.debug.assert;
|
|||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
const TypeId = builtin.TypeId;
|
const TypeId = builtin.TypeId;
|
||||||
|
|
||||||
pub fn log10(x: var) -> @typeOf(x) {
|
pub fn log10(x: var) @typeOf(x) {
|
||||||
const T = @typeOf(x);
|
const T = @typeOf(x);
|
||||||
switch (@typeId(T)) {
|
switch (@typeId(T)) {
|
||||||
TypeId.FloatLiteral => {
|
TypeId.FloatLiteral => {
|
||||||
@ -34,7 +34,7 @@ pub fn log10(x: var) -> @typeOf(x) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn log10_32(x_: f32) -> f32 {
|
pub fn log10_32(x_: f32) f32 {
|
||||||
const ivln10hi: f32 = 4.3432617188e-01;
|
const ivln10hi: f32 = 4.3432617188e-01;
|
||||||
const ivln10lo: f32 = -3.1689971365e-05;
|
const ivln10lo: f32 = -3.1689971365e-05;
|
||||||
const log10_2hi: f32 = 3.0102920532e-01;
|
const log10_2hi: f32 = 3.0102920532e-01;
|
||||||
@ -94,7 +94,7 @@ pub fn log10_32(x_: f32) -> f32 {
|
|||||||
return dk * log10_2lo + (lo + hi) * ivln10lo + lo * ivln10hi + hi * ivln10hi + dk * log10_2hi;
|
return dk * log10_2lo + (lo + hi) * ivln10lo + lo * ivln10hi + hi * ivln10hi + dk * log10_2hi;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn log10_64(x_: f64) -> f64 {
|
pub fn log10_64(x_: f64) f64 {
|
||||||
const ivln10hi: f64 = 4.34294481878168880939e-01;
|
const ivln10hi: f64 = 4.34294481878168880939e-01;
|
||||||
const ivln10lo: f64 = 2.50829467116452752298e-11;
|
const ivln10lo: f64 = 2.50829467116452752298e-11;
|
||||||
const log10_2hi: f64 = 3.01029995663611771306e-01;
|
const log10_2hi: f64 = 3.01029995663611771306e-01;
|
||||||
|
@ -10,7 +10,7 @@ const std = @import("../index.zig");
|
|||||||
const math = std.math;
|
const math = std.math;
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
|
|
||||||
pub fn log1p(x: var) -> @typeOf(x) {
|
pub fn log1p(x: var) @typeOf(x) {
|
||||||
const T = @typeOf(x);
|
const T = @typeOf(x);
|
||||||
return switch (T) {
|
return switch (T) {
|
||||||
f32 => log1p_32(x),
|
f32 => log1p_32(x),
|
||||||
@ -19,7 +19,7 @@ pub fn log1p(x: var) -> @typeOf(x) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn log1p_32(x: f32) -> f32 {
|
fn log1p_32(x: f32) f32 {
|
||||||
const ln2_hi = 6.9313812256e-01;
|
const ln2_hi = 6.9313812256e-01;
|
||||||
const ln2_lo = 9.0580006145e-06;
|
const ln2_lo = 9.0580006145e-06;
|
||||||
const Lg1: f32 = 0xaaaaaa.0p-24;
|
const Lg1: f32 = 0xaaaaaa.0p-24;
|
||||||
@ -95,7 +95,7 @@ fn log1p_32(x: f32) -> f32 {
|
|||||||
return s * (hfsq + R) + (dk * ln2_lo + c) - hfsq + f + dk * ln2_hi;
|
return s * (hfsq + R) + (dk * ln2_lo + c) - hfsq + f + dk * ln2_hi;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn log1p_64(x: f64) -> f64 {
|
fn log1p_64(x: f64) f64 {
|
||||||
const ln2_hi: f64 = 6.93147180369123816490e-01;
|
const ln2_hi: f64 = 6.93147180369123816490e-01;
|
||||||
const ln2_lo: f64 = 1.90821492927058770002e-10;
|
const ln2_lo: f64 = 1.90821492927058770002e-10;
|
||||||
const Lg1: f64 = 6.666666666666735130e-01;
|
const Lg1: f64 = 6.666666666666735130e-01;
|
||||||
|
@ -11,7 +11,7 @@ const assert = std.debug.assert;
|
|||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
const TypeId = builtin.TypeId;
|
const TypeId = builtin.TypeId;
|
||||||
|
|
||||||
pub fn log2(x: var) -> @typeOf(x) {
|
pub fn log2(x: var) @typeOf(x) {
|
||||||
const T = @typeOf(x);
|
const T = @typeOf(x);
|
||||||
switch (@typeId(T)) {
|
switch (@typeId(T)) {
|
||||||
TypeId.FloatLiteral => {
|
TypeId.FloatLiteral => {
|
||||||
@ -37,12 +37,12 @@ pub fn log2(x: var) -> @typeOf(x) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn log2_int(comptime T: type, x: T) -> T {
|
pub fn log2_int(comptime T: type, x: T) T {
|
||||||
assert(x != 0);
|
assert(x != 0);
|
||||||
return T.bit_count - 1 - T(@clz(x));
|
return T.bit_count - 1 - T(@clz(x));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn log2_32(x_: f32) -> f32 {
|
pub fn log2_32(x_: f32) f32 {
|
||||||
const ivln2hi: f32 = 1.4428710938e+00;
|
const ivln2hi: f32 = 1.4428710938e+00;
|
||||||
const ivln2lo: f32 = -1.7605285393e-04;
|
const ivln2lo: f32 = -1.7605285393e-04;
|
||||||
const Lg1: f32 = 0xaaaaaa.0p-24;
|
const Lg1: f32 = 0xaaaaaa.0p-24;
|
||||||
@ -98,7 +98,7 @@ pub fn log2_32(x_: f32) -> f32 {
|
|||||||
return (lo + hi) * ivln2lo + lo * ivln2hi + hi * ivln2hi + f32(k);
|
return (lo + hi) * ivln2lo + lo * ivln2hi + hi * ivln2hi + f32(k);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn log2_64(x_: f64) -> f64 {
|
pub fn log2_64(x_: f64) f64 {
|
||||||
const ivln2hi: f64 = 1.44269504072144627571e+00;
|
const ivln2hi: f64 = 1.44269504072144627571e+00;
|
||||||
const ivln2lo: f64 = 1.67517131648865118353e-10;
|
const ivln2lo: f64 = 1.67517131648865118353e-10;
|
||||||
const Lg1: f64 = 6.666666666666735130e-01;
|
const Lg1: f64 = 6.666666666666735130e-01;
|
||||||
|
@ -7,7 +7,7 @@ const std = @import("../index.zig");
|
|||||||
const math = std.math;
|
const math = std.math;
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
|
|
||||||
fn modf_result(comptime T: type) -> type {
|
fn modf_result(comptime T: type) type {
|
||||||
return struct {
|
return struct {
|
||||||
fpart: T,
|
fpart: T,
|
||||||
ipart: T,
|
ipart: T,
|
||||||
@ -16,7 +16,7 @@ fn modf_result(comptime T: type) -> type {
|
|||||||
pub const modf32_result = modf_result(f32);
|
pub const modf32_result = modf_result(f32);
|
||||||
pub const modf64_result = modf_result(f64);
|
pub const modf64_result = modf_result(f64);
|
||||||
|
|
||||||
pub fn modf(x: var) -> modf_result(@typeOf(x)) {
|
pub fn modf(x: var) modf_result(@typeOf(x)) {
|
||||||
const T = @typeOf(x);
|
const T = @typeOf(x);
|
||||||
return switch (T) {
|
return switch (T) {
|
||||||
f32 => modf32(x),
|
f32 => modf32(x),
|
||||||
@ -25,7 +25,7 @@ pub fn modf(x: var) -> modf_result(@typeOf(x)) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn modf32(x: f32) -> modf32_result {
|
fn modf32(x: f32) modf32_result {
|
||||||
var result: modf32_result = undefined;
|
var result: modf32_result = undefined;
|
||||||
|
|
||||||
const u = @bitCast(u32, x);
|
const u = @bitCast(u32, x);
|
||||||
@ -70,7 +70,7 @@ fn modf32(x: f32) -> modf32_result {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn modf64(x: f64) -> modf64_result {
|
fn modf64(x: f64) modf64_result {
|
||||||
var result: modf64_result = undefined;
|
var result: modf64_result = undefined;
|
||||||
|
|
||||||
const u = @bitCast(u64, x);
|
const u = @bitCast(u64, x);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
const math = @import("index.zig");
|
const math = @import("index.zig");
|
||||||
|
|
||||||
pub fn nan(comptime T: type) -> T {
|
pub fn nan(comptime T: type) T {
|
||||||
return switch (T) {
|
return switch (T) {
|
||||||
f32 => @bitCast(f32, math.nan_u32),
|
f32 => @bitCast(f32, math.nan_u32),
|
||||||
f64 => @bitCast(f64, math.nan_u64),
|
f64 => @bitCast(f64, math.nan_u64),
|
||||||
@ -10,7 +10,7 @@ pub fn nan(comptime T: type) -> T {
|
|||||||
|
|
||||||
// Note: A signalling nan is identical to a standard right now by may have a different bit
|
// Note: A signalling nan is identical to a standard right now by may have a different bit
|
||||||
// representation in the future when required.
|
// representation in the future when required.
|
||||||
pub fn snan(comptime T: type) -> T {
|
pub fn snan(comptime T: type) T {
|
||||||
return switch (T) {
|
return switch (T) {
|
||||||
f32 => @bitCast(f32, math.nan_u32),
|
f32 => @bitCast(f32, math.nan_u32),
|
||||||
f64 => @bitCast(f64, math.nan_u64),
|
f64 => @bitCast(f64, math.nan_u64),
|
||||||
|
@ -27,7 +27,7 @@ const math = std.math;
|
|||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
|
|
||||||
// This implementation is taken from the go stlib, musl is a bit more complex.
|
// This implementation is taken from the go stlib, musl is a bit more complex.
|
||||||
pub fn pow(comptime T: type, x: T, y: T) -> T {
|
pub fn pow(comptime T: type, x: T, y: T) T {
|
||||||
|
|
||||||
@setFloatMode(this, @import("builtin").FloatMode.Strict);
|
@setFloatMode(this, @import("builtin").FloatMode.Strict);
|
||||||
|
|
||||||
@ -170,7 +170,7 @@ pub fn pow(comptime T: type, x: T, y: T) -> T {
|
|||||||
return math.scalbn(a1, ae);
|
return math.scalbn(a1, ae);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn isOddInteger(x: f64) -> bool {
|
fn isOddInteger(x: f64) bool {
|
||||||
const r = math.modf(x);
|
const r = math.modf(x);
|
||||||
return r.fpart == 0.0 and i64(r.ipart) & 1 == 1;
|
return r.fpart == 0.0 and i64(r.ipart) & 1 == 1;
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ const assert = std.debug.assert;
|
|||||||
const std = @import("../index.zig");
|
const std = @import("../index.zig");
|
||||||
const math = std.math;
|
const math = std.math;
|
||||||
|
|
||||||
pub fn round(x: var) -> @typeOf(x) {
|
pub fn round(x: var) @typeOf(x) {
|
||||||
const T = @typeOf(x);
|
const T = @typeOf(x);
|
||||||
return switch (T) {
|
return switch (T) {
|
||||||
f32 => round32(x),
|
f32 => round32(x),
|
||||||
@ -18,7 +18,7 @@ pub fn round(x: var) -> @typeOf(x) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn round32(x_: f32) -> f32 {
|
fn round32(x_: f32) f32 {
|
||||||
var x = x_;
|
var x = x_;
|
||||||
const u = @bitCast(u32, x);
|
const u = @bitCast(u32, x);
|
||||||
const e = (u >> 23) & 0xFF;
|
const e = (u >> 23) & 0xFF;
|
||||||
@ -55,7 +55,7 @@ fn round32(x_: f32) -> f32 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn round64(x_: f64) -> f64 {
|
fn round64(x_: f64) f64 {
|
||||||
var x = x_;
|
var x = x_;
|
||||||
const u = @bitCast(u64, x);
|
const u = @bitCast(u64, x);
|
||||||
const e = (u >> 52) & 0x7FF;
|
const e = (u >> 52) & 0x7FF;
|
||||||
|
@ -2,7 +2,7 @@ const std = @import("../index.zig");
|
|||||||
const math = std.math;
|
const math = std.math;
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
|
|
||||||
pub fn scalbn(x: var, n: i32) -> @typeOf(x) {
|
pub fn scalbn(x: var, n: i32) @typeOf(x) {
|
||||||
const T = @typeOf(x);
|
const T = @typeOf(x);
|
||||||
return switch (T) {
|
return switch (T) {
|
||||||
f32 => scalbn32(x, n),
|
f32 => scalbn32(x, n),
|
||||||
@ -11,7 +11,7 @@ pub fn scalbn(x: var, n: i32) -> @typeOf(x) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scalbn32(x: f32, n_: i32) -> f32 {
|
fn scalbn32(x: f32, n_: i32) f32 {
|
||||||
var y = x;
|
var y = x;
|
||||||
var n = n_;
|
var n = n_;
|
||||||
|
|
||||||
@ -41,7 +41,7 @@ fn scalbn32(x: f32, n_: i32) -> f32 {
|
|||||||
return y * @bitCast(f32, u);
|
return y * @bitCast(f32, u);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scalbn64(x: f64, n_: i32) -> f64 {
|
fn scalbn64(x: f64, n_: i32) f64 {
|
||||||
var y = x;
|
var y = x;
|
||||||
var n = n_;
|
var n = n_;
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ const std = @import("../index.zig");
|
|||||||
const math = std.math;
|
const math = std.math;
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
|
|
||||||
pub fn signbit(x: var) -> bool {
|
pub fn signbit(x: var) bool {
|
||||||
const T = @typeOf(x);
|
const T = @typeOf(x);
|
||||||
return switch (T) {
|
return switch (T) {
|
||||||
f32 => signbit32(x),
|
f32 => signbit32(x),
|
||||||
@ -11,12 +11,12 @@ pub fn signbit(x: var) -> bool {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signbit32(x: f32) -> bool {
|
fn signbit32(x: f32) bool {
|
||||||
const bits = @bitCast(u32, x);
|
const bits = @bitCast(u32, x);
|
||||||
return bits >> 31 != 0;
|
return bits >> 31 != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signbit64(x: f64) -> bool {
|
fn signbit64(x: f64) bool {
|
||||||
const bits = @bitCast(u64, x);
|
const bits = @bitCast(u64, x);
|
||||||
return bits >> 63 != 0;
|
return bits >> 63 != 0;
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ const std = @import("../index.zig");
|
|||||||
const math = std.math;
|
const math = std.math;
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
|
|
||||||
pub fn sin(x: var) -> @typeOf(x) {
|
pub fn sin(x: var) @typeOf(x) {
|
||||||
const T = @typeOf(x);
|
const T = @typeOf(x);
|
||||||
return switch (T) {
|
return switch (T) {
|
||||||
f32 => sin32(x),
|
f32 => sin32(x),
|
||||||
@ -37,7 +37,7 @@ const C5 = 4.16666666666665929218E-2;
|
|||||||
// NOTE: This is taken from the go stdlib. The musl implementation is much more complex.
|
// NOTE: This is taken from the go stdlib. The musl implementation is much more complex.
|
||||||
//
|
//
|
||||||
// This may have slight differences on some edge cases and may need to replaced if so.
|
// This may have slight differences on some edge cases and may need to replaced if so.
|
||||||
fn sin32(x_: f32) -> f32 {
|
fn sin32(x_: f32) f32 {
|
||||||
@setFloatMode(this, @import("builtin").FloatMode.Strict);
|
@setFloatMode(this, @import("builtin").FloatMode.Strict);
|
||||||
|
|
||||||
const pi4a = 7.85398125648498535156e-1;
|
const pi4a = 7.85398125648498535156e-1;
|
||||||
@ -91,7 +91,7 @@ fn sin32(x_: f32) -> f32 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sin64(x_: f64) -> f64 {
|
fn sin64(x_: f64) f64 {
|
||||||
const pi4a = 7.85398125648498535156e-1;
|
const pi4a = 7.85398125648498535156e-1;
|
||||||
const pi4b = 3.77489470793079817668E-8;
|
const pi4b = 3.77489470793079817668E-8;
|
||||||
const pi4c = 2.69515142907905952645E-15;
|
const pi4c = 2.69515142907905952645E-15;
|
||||||
|
@ -10,7 +10,7 @@ const math = std.math;
|
|||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
const expo2 = @import("expo2.zig").expo2;
|
const expo2 = @import("expo2.zig").expo2;
|
||||||
|
|
||||||
pub fn sinh(x: var) -> @typeOf(x) {
|
pub fn sinh(x: var) @typeOf(x) {
|
||||||
const T = @typeOf(x);
|
const T = @typeOf(x);
|
||||||
return switch (T) {
|
return switch (T) {
|
||||||
f32 => sinh32(x),
|
f32 => sinh32(x),
|
||||||
@ -22,7 +22,7 @@ pub fn sinh(x: var) -> @typeOf(x) {
|
|||||||
// sinh(x) = (exp(x) - 1 / exp(x)) / 2
|
// sinh(x) = (exp(x) - 1 / exp(x)) / 2
|
||||||
// = (exp(x) - 1 + (exp(x) - 1) / exp(x)) / 2
|
// = (exp(x) - 1 + (exp(x) - 1) / exp(x)) / 2
|
||||||
// = x + x^3 / 6 + o(x^5)
|
// = x + x^3 / 6 + o(x^5)
|
||||||
fn sinh32(x: f32) -> f32 {
|
fn sinh32(x: f32) f32 {
|
||||||
const u = @bitCast(u32, x);
|
const u = @bitCast(u32, x);
|
||||||
const ux = u & 0x7FFFFFFF;
|
const ux = u & 0x7FFFFFFF;
|
||||||
const ax = @bitCast(f32, ux);
|
const ax = @bitCast(f32, ux);
|
||||||
@ -53,7 +53,7 @@ fn sinh32(x: f32) -> f32 {
|
|||||||
return 2 * h * expo2(ax);
|
return 2 * h * expo2(ax);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sinh64(x: f64) -> f64 {
|
fn sinh64(x: f64) f64 {
|
||||||
@setFloatMode(this, @import("builtin").FloatMode.Strict);
|
@setFloatMode(this, @import("builtin").FloatMode.Strict);
|
||||||
|
|
||||||
const u = @bitCast(u64, x);
|
const u = @bitCast(u64, x);
|
||||||
|
@ -11,7 +11,7 @@ const assert = std.debug.assert;
|
|||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
const TypeId = builtin.TypeId;
|
const TypeId = builtin.TypeId;
|
||||||
|
|
||||||
pub fn sqrt(x: var) -> (if (@typeId(@typeOf(x)) == TypeId.Int) @IntType(false, @typeOf(x).bit_count / 2) else @typeOf(x)) {
|
pub fn sqrt(x: var) (if (@typeId(@typeOf(x)) == TypeId.Int) @IntType(false, @typeOf(x).bit_count / 2) else @typeOf(x)) {
|
||||||
const T = @typeOf(x);
|
const T = @typeOf(x);
|
||||||
switch (@typeId(T)) {
|
switch (@typeId(T)) {
|
||||||
TypeId.FloatLiteral => {
|
TypeId.FloatLiteral => {
|
||||||
@ -50,7 +50,7 @@ pub fn sqrt(x: var) -> (if (@typeId(@typeOf(x)) == TypeId.Int) @IntType(false, @
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sqrt32(x: f32) -> f32 {
|
fn sqrt32(x: f32) f32 {
|
||||||
const tiny: f32 = 1.0e-30;
|
const tiny: f32 = 1.0e-30;
|
||||||
const sign: i32 = @bitCast(i32, u32(0x80000000));
|
const sign: i32 = @bitCast(i32, u32(0x80000000));
|
||||||
var ix: i32 = @bitCast(i32, x);
|
var ix: i32 = @bitCast(i32, x);
|
||||||
@ -129,7 +129,7 @@ fn sqrt32(x: f32) -> f32 {
|
|||||||
// NOTE: The original code is full of implicit signed -> unsigned assumptions and u32 wraparound
|
// NOTE: The original code is full of implicit signed -> unsigned assumptions and u32 wraparound
|
||||||
// behaviour. Most intermediate i32 values are changed to u32 where appropriate but there are
|
// behaviour. Most intermediate i32 values are changed to u32 where appropriate but there are
|
||||||
// potentially some edge cases remaining that are not handled in the same way.
|
// potentially some edge cases remaining that are not handled in the same way.
|
||||||
fn sqrt64(x: f64) -> f64 {
|
fn sqrt64(x: f64) f64 {
|
||||||
const tiny: f64 = 1.0e-300;
|
const tiny: f64 = 1.0e-300;
|
||||||
const sign: u32 = 0x80000000;
|
const sign: u32 = 0x80000000;
|
||||||
const u = @bitCast(u64, x);
|
const u = @bitCast(u64, x);
|
||||||
@ -308,7 +308,7 @@ test "math.sqrt64.special" {
|
|||||||
assert(math.isNan(sqrt64(math.nan(f64))));
|
assert(math.isNan(sqrt64(math.nan(f64))));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sqrt_int(comptime T: type, value: T) -> @IntType(false, T.bit_count / 2) {
|
fn sqrt_int(comptime T: type, value: T) @IntType(false, T.bit_count / 2) {
|
||||||
var op = value;
|
var op = value;
|
||||||
var res: T = 0;
|
var res: T = 0;
|
||||||
var one: T = 1 << (T.bit_count - 2);
|
var one: T = 1 << (T.bit_count - 2);
|
||||||
|
@ -9,7 +9,7 @@ const std = @import("../index.zig");
|
|||||||
const math = std.math;
|
const math = std.math;
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
|
|
||||||
pub fn tan(x: var) -> @typeOf(x) {
|
pub fn tan(x: var) @typeOf(x) {
|
||||||
const T = @typeOf(x);
|
const T = @typeOf(x);
|
||||||
return switch (T) {
|
return switch (T) {
|
||||||
f32 => tan32(x),
|
f32 => tan32(x),
|
||||||
@ -30,7 +30,7 @@ const Tq4 = -5.38695755929454629881E7;
|
|||||||
// NOTE: This is taken from the go stdlib. The musl implementation is much more complex.
|
// NOTE: This is taken from the go stdlib. The musl implementation is much more complex.
|
||||||
//
|
//
|
||||||
// This may have slight differences on some edge cases and may need to replaced if so.
|
// This may have slight differences on some edge cases and may need to replaced if so.
|
||||||
fn tan32(x_: f32) -> f32 {
|
fn tan32(x_: f32) f32 {
|
||||||
@setFloatMode(this, @import("builtin").FloatMode.Strict);
|
@setFloatMode(this, @import("builtin").FloatMode.Strict);
|
||||||
|
|
||||||
const pi4a = 7.85398125648498535156e-1;
|
const pi4a = 7.85398125648498535156e-1;
|
||||||
@ -81,7 +81,7 @@ fn tan32(x_: f32) -> f32 {
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tan64(x_: f64) -> f64 {
|
fn tan64(x_: f64) f64 {
|
||||||
const pi4a = 7.85398125648498535156e-1;
|
const pi4a = 7.85398125648498535156e-1;
|
||||||
const pi4b = 3.77489470793079817668E-8;
|
const pi4b = 3.77489470793079817668E-8;
|
||||||
const pi4c = 2.69515142907905952645E-15;
|
const pi4c = 2.69515142907905952645E-15;
|
||||||
|
@ -10,7 +10,7 @@ const math = std.math;
|
|||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
const expo2 = @import("expo2.zig").expo2;
|
const expo2 = @import("expo2.zig").expo2;
|
||||||
|
|
||||||
pub fn tanh(x: var) -> @typeOf(x) {
|
pub fn tanh(x: var) @typeOf(x) {
|
||||||
const T = @typeOf(x);
|
const T = @typeOf(x);
|
||||||
return switch (T) {
|
return switch (T) {
|
||||||
f32 => tanh32(x),
|
f32 => tanh32(x),
|
||||||
@ -22,7 +22,7 @@ pub fn tanh(x: var) -> @typeOf(x) {
|
|||||||
// tanh(x) = (exp(x) - exp(-x)) / (exp(x) + exp(-x))
|
// tanh(x) = (exp(x) - exp(-x)) / (exp(x) + exp(-x))
|
||||||
// = (exp(2x) - 1) / (exp(2x) - 1 + 2)
|
// = (exp(2x) - 1) / (exp(2x) - 1 + 2)
|
||||||
// = (1 - exp(-2x)) / (exp(-2x) - 1 + 2)
|
// = (1 - exp(-2x)) / (exp(-2x) - 1 + 2)
|
||||||
fn tanh32(x: f32) -> f32 {
|
fn tanh32(x: f32) f32 {
|
||||||
const u = @bitCast(u32, x);
|
const u = @bitCast(u32, x);
|
||||||
const ux = u & 0x7FFFFFFF;
|
const ux = u & 0x7FFFFFFF;
|
||||||
const ax = @bitCast(f32, ux);
|
const ax = @bitCast(f32, ux);
|
||||||
@ -66,7 +66,7 @@ fn tanh32(x: f32) -> f32 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tanh64(x: f64) -> f64 {
|
fn tanh64(x: f64) f64 {
|
||||||
const u = @bitCast(u64, x);
|
const u = @bitCast(u64, x);
|
||||||
const w = u32(u >> 32);
|
const w = u32(u >> 32);
|
||||||
const ax = @bitCast(f64, u & (@maxValue(u64) >> 1));
|
const ax = @bitCast(f64, u & (@maxValue(u64) >> 1));
|
||||||
|
@ -8,7 +8,7 @@ const std = @import("../index.zig");
|
|||||||
const math = std.math;
|
const math = std.math;
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
|
|
||||||
pub fn trunc(x: var) -> @typeOf(x) {
|
pub fn trunc(x: var) @typeOf(x) {
|
||||||
const T = @typeOf(x);
|
const T = @typeOf(x);
|
||||||
return switch (T) {
|
return switch (T) {
|
||||||
f32 => trunc32(x),
|
f32 => trunc32(x),
|
||||||
@ -17,7 +17,7 @@ pub fn trunc(x: var) -> @typeOf(x) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn trunc32(x: f32) -> f32 {
|
fn trunc32(x: f32) f32 {
|
||||||
const u = @bitCast(u32, x);
|
const u = @bitCast(u32, x);
|
||||||
var e = i32(((u >> 23) & 0xFF)) - 0x7F + 9;
|
var e = i32(((u >> 23) & 0xFF)) - 0x7F + 9;
|
||||||
var m: u32 = undefined;
|
var m: u32 = undefined;
|
||||||
@ -38,7 +38,7 @@ fn trunc32(x: f32) -> f32 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn trunc64(x: f64) -> f64 {
|
fn trunc64(x: f64) f64 {
|
||||||
const u = @bitCast(u64, x);
|
const u = @bitCast(u64, x);
|
||||||
var e = i32(((u >> 52) & 0x7FF)) - 0x3FF + 12;
|
var e = i32(((u >> 52) & 0x7FF)) - 0x3FF + 12;
|
||||||
var m: u64 = undefined;
|
var m: u64 = undefined;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
pub fn sqrt32(x: f32) -> f32 {
|
pub fn sqrt32(x: f32) f32 {
|
||||||
return asm (
|
return asm (
|
||||||
\\sqrtss %%xmm0, %%xmm0
|
\\sqrtss %%xmm0, %%xmm0
|
||||||
: [ret] "={xmm0}" (-> f32)
|
: [ret] "={xmm0}" (-> f32)
|
||||||
@ -6,7 +6,7 @@ pub fn sqrt32(x: f32) -> f32 {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sqrt64(x: f64) -> f64 {
|
pub fn sqrt64(x: f64) f64 {
|
||||||
return asm (
|
return asm (
|
||||||
\\sqrtsd %%xmm0, %%xmm0
|
\\sqrtsd %%xmm0, %%xmm0
|
||||||
: [ret] "={xmm0}" (-> f64)
|
: [ret] "={xmm0}" (-> f64)
|
||||||
|
94
std/mem.zig
94
std/mem.zig
@ -10,7 +10,7 @@ pub const Allocator = struct {
|
|||||||
/// Allocate byte_count bytes and return them in a slice, with the
|
/// Allocate byte_count bytes and return them in a slice, with the
|
||||||
/// slice's pointer aligned at least to alignment bytes.
|
/// slice's pointer aligned at least to alignment bytes.
|
||||||
/// The returned newly allocated memory is undefined.
|
/// The returned newly allocated memory is undefined.
|
||||||
allocFn: fn (self: &Allocator, byte_count: usize, alignment: u29) -> %[]u8,
|
allocFn: fn (self: &Allocator, byte_count: usize, alignment: u29) %[]u8,
|
||||||
|
|
||||||
/// If `new_byte_count > old_mem.len`:
|
/// If `new_byte_count > old_mem.len`:
|
||||||
/// * `old_mem.len` is the same as what was returned from allocFn or reallocFn.
|
/// * `old_mem.len` is the same as what was returned from allocFn or reallocFn.
|
||||||
@ -21,26 +21,26 @@ pub const Allocator = struct {
|
|||||||
/// * alignment <= alignment of old_mem.ptr
|
/// * alignment <= alignment of old_mem.ptr
|
||||||
///
|
///
|
||||||
/// The returned newly allocated memory is undefined.
|
/// The returned newly allocated memory is undefined.
|
||||||
reallocFn: fn (self: &Allocator, old_mem: []u8, new_byte_count: usize, alignment: u29) -> %[]u8,
|
reallocFn: fn (self: &Allocator, old_mem: []u8, new_byte_count: usize, alignment: u29) %[]u8,
|
||||||
|
|
||||||
/// Guaranteed: `old_mem.len` is the same as what was returned from `allocFn` or `reallocFn`
|
/// Guaranteed: `old_mem.len` is the same as what was returned from `allocFn` or `reallocFn`
|
||||||
freeFn: fn (self: &Allocator, old_mem: []u8),
|
freeFn: fn (self: &Allocator, old_mem: []u8) void,
|
||||||
|
|
||||||
fn create(self: &Allocator, comptime T: type) -> %&T {
|
fn create(self: &Allocator, comptime T: type) %&T {
|
||||||
const slice = try self.alloc(T, 1);
|
const slice = try self.alloc(T, 1);
|
||||||
return &slice[0];
|
return &slice[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
fn destroy(self: &Allocator, ptr: var) {
|
fn destroy(self: &Allocator, ptr: var) void {
|
||||||
self.free(ptr[0..1]);
|
self.free(ptr[0..1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn alloc(self: &Allocator, comptime T: type, n: usize) -> %[]T {
|
fn alloc(self: &Allocator, comptime T: type, n: usize) %[]T {
|
||||||
return self.alignedAlloc(T, @alignOf(T), n);
|
return self.alignedAlloc(T, @alignOf(T), n);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn alignedAlloc(self: &Allocator, comptime T: type, comptime alignment: u29,
|
fn alignedAlloc(self: &Allocator, comptime T: type, comptime alignment: u29,
|
||||||
n: usize) -> %[]align(alignment) T
|
n: usize) %[]align(alignment) T
|
||||||
{
|
{
|
||||||
const byte_count = try math.mul(usize, @sizeOf(T), n);
|
const byte_count = try math.mul(usize, @sizeOf(T), n);
|
||||||
const byte_slice = try self.allocFn(self, byte_count, alignment);
|
const byte_slice = try self.allocFn(self, byte_count, alignment);
|
||||||
@ -51,12 +51,12 @@ pub const Allocator = struct {
|
|||||||
return ([]align(alignment) T)(@alignCast(alignment, byte_slice));
|
return ([]align(alignment) T)(@alignCast(alignment, byte_slice));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn realloc(self: &Allocator, comptime T: type, old_mem: []T, n: usize) -> %[]T {
|
fn realloc(self: &Allocator, comptime T: type, old_mem: []T, n: usize) %[]T {
|
||||||
return self.alignedRealloc(T, @alignOf(T), @alignCast(@alignOf(T), old_mem), n);
|
return self.alignedRealloc(T, @alignOf(T), @alignCast(@alignOf(T), old_mem), n);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn alignedRealloc(self: &Allocator, comptime T: type, comptime alignment: u29,
|
fn alignedRealloc(self: &Allocator, comptime T: type, comptime alignment: u29,
|
||||||
old_mem: []align(alignment) T, n: usize) -> %[]align(alignment) T
|
old_mem: []align(alignment) T, n: usize) %[]align(alignment) T
|
||||||
{
|
{
|
||||||
if (old_mem.len == 0) {
|
if (old_mem.len == 0) {
|
||||||
return self.alloc(T, n);
|
return self.alloc(T, n);
|
||||||
@ -75,12 +75,12 @@ pub const Allocator = struct {
|
|||||||
/// Reallocate, but `n` must be less than or equal to `old_mem.len`.
|
/// Reallocate, but `n` must be less than or equal to `old_mem.len`.
|
||||||
/// Unlike `realloc`, this function cannot fail.
|
/// Unlike `realloc`, this function cannot fail.
|
||||||
/// Shrinking to 0 is the same as calling `free`.
|
/// Shrinking to 0 is the same as calling `free`.
|
||||||
fn shrink(self: &Allocator, comptime T: type, old_mem: []T, n: usize) -> []T {
|
fn shrink(self: &Allocator, comptime T: type, old_mem: []T, n: usize) []T {
|
||||||
return self.alignedShrink(T, @alignOf(T), @alignCast(@alignOf(T), old_mem), n);
|
return self.alignedShrink(T, @alignOf(T), @alignCast(@alignOf(T), old_mem), n);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn alignedShrink(self: &Allocator, comptime T: type, comptime alignment: u29,
|
fn alignedShrink(self: &Allocator, comptime T: type, comptime alignment: u29,
|
||||||
old_mem: []align(alignment) T, n: usize) -> []align(alignment) T
|
old_mem: []align(alignment) T, n: usize) []align(alignment) T
|
||||||
{
|
{
|
||||||
if (n == 0) {
|
if (n == 0) {
|
||||||
self.free(old_mem);
|
self.free(old_mem);
|
||||||
@ -97,7 +97,7 @@ pub const Allocator = struct {
|
|||||||
return ([]align(alignment) T)(@alignCast(alignment, byte_slice));
|
return ([]align(alignment) T)(@alignCast(alignment, byte_slice));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn free(self: &Allocator, memory: var) {
|
fn free(self: &Allocator, memory: var) void {
|
||||||
const bytes = ([]const u8)(memory);
|
const bytes = ([]const u8)(memory);
|
||||||
if (bytes.len == 0)
|
if (bytes.len == 0)
|
||||||
return;
|
return;
|
||||||
@ -111,7 +111,7 @@ pub const FixedBufferAllocator = struct {
|
|||||||
end_index: usize,
|
end_index: usize,
|
||||||
buffer: []u8,
|
buffer: []u8,
|
||||||
|
|
||||||
pub fn init(buffer: []u8) -> FixedBufferAllocator {
|
pub fn init(buffer: []u8) FixedBufferAllocator {
|
||||||
return FixedBufferAllocator {
|
return FixedBufferAllocator {
|
||||||
.allocator = Allocator {
|
.allocator = Allocator {
|
||||||
.allocFn = alloc,
|
.allocFn = alloc,
|
||||||
@ -123,7 +123,7 @@ pub const FixedBufferAllocator = struct {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn alloc(allocator: &Allocator, n: usize, alignment: u29) -> %[]u8 {
|
fn alloc(allocator: &Allocator, n: usize, alignment: u29) %[]u8 {
|
||||||
const self = @fieldParentPtr(FixedBufferAllocator, "allocator", allocator);
|
const self = @fieldParentPtr(FixedBufferAllocator, "allocator", allocator);
|
||||||
const addr = @ptrToInt(&self.buffer[self.end_index]);
|
const addr = @ptrToInt(&self.buffer[self.end_index]);
|
||||||
const rem = @rem(addr, alignment);
|
const rem = @rem(addr, alignment);
|
||||||
@ -138,7 +138,7 @@ pub const FixedBufferAllocator = struct {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn realloc(allocator: &Allocator, old_mem: []u8, new_size: usize, alignment: u29) -> %[]u8 {
|
fn realloc(allocator: &Allocator, old_mem: []u8, new_size: usize, alignment: u29) %[]u8 {
|
||||||
if (new_size <= old_mem.len) {
|
if (new_size <= old_mem.len) {
|
||||||
return old_mem[0..new_size];
|
return old_mem[0..new_size];
|
||||||
} else {
|
} else {
|
||||||
@ -148,13 +148,13 @@ pub const FixedBufferAllocator = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn free(allocator: &Allocator, bytes: []u8) { }
|
fn free(allocator: &Allocator, bytes: []u8) void { }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/// Copy all of source into dest at position 0.
|
/// Copy all of source into dest at position 0.
|
||||||
/// dest.len must be >= source.len.
|
/// dest.len must be >= source.len.
|
||||||
pub fn copy(comptime T: type, dest: []T, source: []const T) {
|
pub fn copy(comptime T: type, dest: []T, source: []const T) void {
|
||||||
// TODO instead of manually doing this check for the whole array
|
// TODO instead of manually doing this check for the whole array
|
||||||
// and turning off runtime safety, the compiler should detect loops like
|
// and turning off runtime safety, the compiler should detect loops like
|
||||||
// this and automatically omit safety checks for loops
|
// this and automatically omit safety checks for loops
|
||||||
@ -163,12 +163,12 @@ pub fn copy(comptime T: type, dest: []T, source: []const T) {
|
|||||||
for (source) |s, i| dest[i] = s;
|
for (source) |s, i| dest[i] = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set(comptime T: type, dest: []T, value: T) {
|
pub fn set(comptime T: type, dest: []T, value: T) void {
|
||||||
for (dest) |*d| *d = value;
|
for (dest) |*d| *d = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if lhs < rhs, false otherwise
|
/// Returns true if lhs < rhs, false otherwise
|
||||||
pub fn lessThan(comptime T: type, lhs: []const T, rhs: []const T) -> bool {
|
pub fn lessThan(comptime T: type, lhs: []const T, rhs: []const T) bool {
|
||||||
const n = math.min(lhs.len, rhs.len);
|
const n = math.min(lhs.len, rhs.len);
|
||||||
var i: usize = 0;
|
var i: usize = 0;
|
||||||
while (i < n) : (i += 1) {
|
while (i < n) : (i += 1) {
|
||||||
@ -188,7 +188,7 @@ test "mem.lessThan" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Compares two slices and returns whether they are equal.
|
/// Compares two slices and returns whether they are equal.
|
||||||
pub fn eql(comptime T: type, a: []const T, b: []const T) -> bool {
|
pub fn eql(comptime T: type, a: []const T, b: []const T) bool {
|
||||||
if (a.len != b.len) return false;
|
if (a.len != b.len) return false;
|
||||||
for (a) |item, index| {
|
for (a) |item, index| {
|
||||||
if (b[index] != item) return false;
|
if (b[index] != item) return false;
|
||||||
@ -197,14 +197,14 @@ pub fn eql(comptime T: type, a: []const T, b: []const T) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Copies ::m to newly allocated memory. Caller is responsible to free it.
|
/// Copies ::m to newly allocated memory. Caller is responsible to free it.
|
||||||
pub fn dupe(allocator: &Allocator, comptime T: type, m: []const T) -> %[]T {
|
pub fn dupe(allocator: &Allocator, comptime T: type, m: []const T) %[]T {
|
||||||
const new_buf = try allocator.alloc(T, m.len);
|
const new_buf = try allocator.alloc(T, m.len);
|
||||||
copy(T, new_buf, m);
|
copy(T, new_buf, m);
|
||||||
return new_buf;
|
return new_buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Remove values from the beginning and end of a slice.
|
/// Remove values from the beginning and end of a slice.
|
||||||
pub fn trim(comptime T: type, slice: []const T, values_to_strip: []const T) -> []const T {
|
pub fn trim(comptime T: type, slice: []const T, values_to_strip: []const T) []const T {
|
||||||
var begin: usize = 0;
|
var begin: usize = 0;
|
||||||
var end: usize = slice.len;
|
var end: usize = slice.len;
|
||||||
while (begin < end and indexOfScalar(T, values_to_strip, slice[begin]) != null) : (begin += 1) {}
|
while (begin < end and indexOfScalar(T, values_to_strip, slice[begin]) != null) : (begin += 1) {}
|
||||||
@ -218,11 +218,11 @@ test "mem.trim" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Linear search for the index of a scalar value inside a slice.
|
/// Linear search for the index of a scalar value inside a slice.
|
||||||
pub fn indexOfScalar(comptime T: type, slice: []const T, value: T) -> ?usize {
|
pub fn indexOfScalar(comptime T: type, slice: []const T, value: T) ?usize {
|
||||||
return indexOfScalarPos(T, slice, 0, value);
|
return indexOfScalarPos(T, slice, 0, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn indexOfScalarPos(comptime T: type, slice: []const T, start_index: usize, value: T) -> ?usize {
|
pub fn indexOfScalarPos(comptime T: type, slice: []const T, start_index: usize, value: T) ?usize {
|
||||||
var i: usize = start_index;
|
var i: usize = start_index;
|
||||||
while (i < slice.len) : (i += 1) {
|
while (i < slice.len) : (i += 1) {
|
||||||
if (slice[i] == value)
|
if (slice[i] == value)
|
||||||
@ -231,11 +231,11 @@ pub fn indexOfScalarPos(comptime T: type, slice: []const T, start_index: usize,
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn indexOfAny(comptime T: type, slice: []const T, values: []const T) -> ?usize {
|
pub fn indexOfAny(comptime T: type, slice: []const T, values: []const T) ?usize {
|
||||||
return indexOfAnyPos(T, slice, 0, values);
|
return indexOfAnyPos(T, slice, 0, values);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn indexOfAnyPos(comptime T: type, slice: []const T, start_index: usize, values: []const T) -> ?usize {
|
pub fn indexOfAnyPos(comptime T: type, slice: []const T, start_index: usize, values: []const T) ?usize {
|
||||||
var i: usize = start_index;
|
var i: usize = start_index;
|
||||||
while (i < slice.len) : (i += 1) {
|
while (i < slice.len) : (i += 1) {
|
||||||
for (values) |value| {
|
for (values) |value| {
|
||||||
@ -246,12 +246,12 @@ pub fn indexOfAnyPos(comptime T: type, slice: []const T, start_index: usize, val
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn indexOf(comptime T: type, haystack: []const T, needle: []const T) -> ?usize {
|
pub fn indexOf(comptime T: type, haystack: []const T, needle: []const T) ?usize {
|
||||||
return indexOfPos(T, haystack, 0, needle);
|
return indexOfPos(T, haystack, 0, needle);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO boyer-moore algorithm
|
// TODO boyer-moore algorithm
|
||||||
pub fn indexOfPos(comptime T: type, haystack: []const T, start_index: usize, needle: []const T) -> ?usize {
|
pub fn indexOfPos(comptime T: type, haystack: []const T, start_index: usize, needle: []const T) ?usize {
|
||||||
if (needle.len > haystack.len)
|
if (needle.len > haystack.len)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
@ -275,7 +275,7 @@ test "mem.indexOf" {
|
|||||||
/// T specifies the return type, which must be large enough to store
|
/// T specifies the return type, which must be large enough to store
|
||||||
/// the result.
|
/// the result.
|
||||||
/// See also ::readIntBE or ::readIntLE.
|
/// See also ::readIntBE or ::readIntLE.
|
||||||
pub fn readInt(bytes: []const u8, comptime T: type, endian: builtin.Endian) -> T {
|
pub fn readInt(bytes: []const u8, comptime T: type, endian: builtin.Endian) T {
|
||||||
if (T.bit_count == 8) {
|
if (T.bit_count == 8) {
|
||||||
return bytes[0];
|
return bytes[0];
|
||||||
}
|
}
|
||||||
@ -298,7 +298,7 @@ pub fn readInt(bytes: []const u8, comptime T: type, endian: builtin.Endian) -> T
|
|||||||
|
|
||||||
/// Reads a big-endian int of type T from bytes.
|
/// Reads a big-endian int of type T from bytes.
|
||||||
/// bytes.len must be exactly @sizeOf(T).
|
/// bytes.len must be exactly @sizeOf(T).
|
||||||
pub fn readIntBE(comptime T: type, bytes: []const u8) -> T {
|
pub fn readIntBE(comptime T: type, bytes: []const u8) T {
|
||||||
if (T.is_signed) {
|
if (T.is_signed) {
|
||||||
return @bitCast(T, readIntBE(@IntType(false, T.bit_count), bytes));
|
return @bitCast(T, readIntBE(@IntType(false, T.bit_count), bytes));
|
||||||
}
|
}
|
||||||
@ -312,7 +312,7 @@ pub fn readIntBE(comptime T: type, bytes: []const u8) -> T {
|
|||||||
|
|
||||||
/// Reads a little-endian int of type T from bytes.
|
/// Reads a little-endian int of type T from bytes.
|
||||||
/// bytes.len must be exactly @sizeOf(T).
|
/// bytes.len must be exactly @sizeOf(T).
|
||||||
pub fn readIntLE(comptime T: type, bytes: []const u8) -> T {
|
pub fn readIntLE(comptime T: type, bytes: []const u8) T {
|
||||||
if (T.is_signed) {
|
if (T.is_signed) {
|
||||||
return @bitCast(T, readIntLE(@IntType(false, T.bit_count), bytes));
|
return @bitCast(T, readIntLE(@IntType(false, T.bit_count), bytes));
|
||||||
}
|
}
|
||||||
@ -327,7 +327,7 @@ pub fn readIntLE(comptime T: type, bytes: []const u8) -> T {
|
|||||||
/// Writes an integer to memory with size equal to bytes.len. Pads with zeroes
|
/// Writes an integer to memory with size equal to bytes.len. Pads with zeroes
|
||||||
/// to fill the entire buffer provided.
|
/// to fill the entire buffer provided.
|
||||||
/// value must be an integer.
|
/// value must be an integer.
|
||||||
pub fn writeInt(buf: []u8, value: var, endian: builtin.Endian) {
|
pub fn writeInt(buf: []u8, value: var, endian: builtin.Endian) void {
|
||||||
const uint = @IntType(false, @typeOf(value).bit_count);
|
const uint = @IntType(false, @typeOf(value).bit_count);
|
||||||
var bits = @truncate(uint, value);
|
var bits = @truncate(uint, value);
|
||||||
switch (endian) {
|
switch (endian) {
|
||||||
@ -351,7 +351,7 @@ pub fn writeInt(buf: []u8, value: var, endian: builtin.Endian) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn hash_slice_u8(k: []const u8) -> u32 {
|
pub fn hash_slice_u8(k: []const u8) u32 {
|
||||||
// FNV 32-bit hash
|
// FNV 32-bit hash
|
||||||
var h: u32 = 2166136261;
|
var h: u32 = 2166136261;
|
||||||
for (k) |b| {
|
for (k) |b| {
|
||||||
@ -360,7 +360,7 @@ pub fn hash_slice_u8(k: []const u8) -> u32 {
|
|||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn eql_slice_u8(a: []const u8, b: []const u8) -> bool {
|
pub fn eql_slice_u8(a: []const u8, b: []const u8) bool {
|
||||||
return eql(u8, a, b);
|
return eql(u8, a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -368,7 +368,7 @@ pub fn eql_slice_u8(a: []const u8, b: []const u8) -> bool {
|
|||||||
/// any of the bytes in `split_bytes`.
|
/// any of the bytes in `split_bytes`.
|
||||||
/// split(" abc def ghi ", " ")
|
/// split(" abc def ghi ", " ")
|
||||||
/// Will return slices for "abc", "def", "ghi", null, in that order.
|
/// Will return slices for "abc", "def", "ghi", null, in that order.
|
||||||
pub fn split(buffer: []const u8, split_bytes: []const u8) -> SplitIterator {
|
pub fn split(buffer: []const u8, split_bytes: []const u8) SplitIterator {
|
||||||
return SplitIterator {
|
return SplitIterator {
|
||||||
.index = 0,
|
.index = 0,
|
||||||
.buffer = buffer,
|
.buffer = buffer,
|
||||||
@ -384,7 +384,7 @@ test "mem.split" {
|
|||||||
assert(it.next() == null);
|
assert(it.next() == null);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn startsWith(comptime T: type, haystack: []const T, needle: []const T) -> bool {
|
pub fn startsWith(comptime T: type, haystack: []const T, needle: []const T) bool {
|
||||||
return if (needle.len > haystack.len) false else eql(T, haystack[0 .. needle.len], needle);
|
return if (needle.len > haystack.len) false else eql(T, haystack[0 .. needle.len], needle);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -393,7 +393,7 @@ const SplitIterator = struct {
|
|||||||
split_bytes: []const u8,
|
split_bytes: []const u8,
|
||||||
index: usize,
|
index: usize,
|
||||||
|
|
||||||
pub fn next(self: &SplitIterator) -> ?[]const u8 {
|
pub fn next(self: &SplitIterator) ?[]const u8 {
|
||||||
// move to beginning of token
|
// move to beginning of token
|
||||||
while (self.index < self.buffer.len and self.isSplitByte(self.buffer[self.index])) : (self.index += 1) {}
|
while (self.index < self.buffer.len and self.isSplitByte(self.buffer[self.index])) : (self.index += 1) {}
|
||||||
const start = self.index;
|
const start = self.index;
|
||||||
@ -409,14 +409,14 @@ const SplitIterator = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a slice of the remaining bytes. Does not affect iterator state.
|
/// Returns a slice of the remaining bytes. Does not affect iterator state.
|
||||||
pub fn rest(self: &const SplitIterator) -> []const u8 {
|
pub fn rest(self: &const SplitIterator) []const u8 {
|
||||||
// move to beginning of token
|
// move to beginning of token
|
||||||
var index: usize = self.index;
|
var index: usize = self.index;
|
||||||
while (index < self.buffer.len and self.isSplitByte(self.buffer[index])) : (index += 1) {}
|
while (index < self.buffer.len and self.isSplitByte(self.buffer[index])) : (index += 1) {}
|
||||||
return self.buffer[index..];
|
return self.buffer[index..];
|
||||||
}
|
}
|
||||||
|
|
||||||
fn isSplitByte(self: &const SplitIterator, byte: u8) -> bool {
|
fn isSplitByte(self: &const SplitIterator, byte: u8) bool {
|
||||||
for (self.split_bytes) |split_byte| {
|
for (self.split_bytes) |split_byte| {
|
||||||
if (byte == split_byte) {
|
if (byte == split_byte) {
|
||||||
return true;
|
return true;
|
||||||
@ -428,7 +428,7 @@ const SplitIterator = struct {
|
|||||||
|
|
||||||
/// Naively combines a series of strings with a separator.
|
/// Naively combines a series of strings with a separator.
|
||||||
/// Allocates memory for the result, which must be freed by the caller.
|
/// Allocates memory for the result, which must be freed by the caller.
|
||||||
pub fn join(allocator: &Allocator, sep: u8, strings: ...) -> %[]u8 {
|
pub fn join(allocator: &Allocator, sep: u8, strings: ...) %[]u8 {
|
||||||
comptime assert(strings.len >= 1);
|
comptime assert(strings.len >= 1);
|
||||||
var total_strings_len: usize = strings.len; // 1 sep per string
|
var total_strings_len: usize = strings.len; // 1 sep per string
|
||||||
{
|
{
|
||||||
@ -474,7 +474,7 @@ test "testReadInt" {
|
|||||||
testReadIntImpl();
|
testReadIntImpl();
|
||||||
comptime testReadIntImpl();
|
comptime testReadIntImpl();
|
||||||
}
|
}
|
||||||
fn testReadIntImpl() {
|
fn testReadIntImpl() void {
|
||||||
{
|
{
|
||||||
const bytes = []u8{ 0x12, 0x34, 0x56, 0x78 };
|
const bytes = []u8{ 0x12, 0x34, 0x56, 0x78 };
|
||||||
assert(readInt(bytes, u32, builtin.Endian.Big) == 0x12345678);
|
assert(readInt(bytes, u32, builtin.Endian.Big) == 0x12345678);
|
||||||
@ -507,7 +507,7 @@ test "testWriteInt" {
|
|||||||
testWriteIntImpl();
|
testWriteIntImpl();
|
||||||
comptime testWriteIntImpl();
|
comptime testWriteIntImpl();
|
||||||
}
|
}
|
||||||
fn testWriteIntImpl() {
|
fn testWriteIntImpl() void {
|
||||||
var bytes: [4]u8 = undefined;
|
var bytes: [4]u8 = undefined;
|
||||||
|
|
||||||
writeInt(bytes[0..], u32(0x12345678), builtin.Endian.Big);
|
writeInt(bytes[0..], u32(0x12345678), builtin.Endian.Big);
|
||||||
@ -524,7 +524,7 @@ fn testWriteIntImpl() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn min(comptime T: type, slice: []const T) -> T {
|
pub fn min(comptime T: type, slice: []const T) T {
|
||||||
var best = slice[0];
|
var best = slice[0];
|
||||||
for (slice[1..]) |item| {
|
for (slice[1..]) |item| {
|
||||||
best = math.min(best, item);
|
best = math.min(best, item);
|
||||||
@ -536,7 +536,7 @@ test "mem.min" {
|
|||||||
assert(min(u8, "abcdefg") == 'a');
|
assert(min(u8, "abcdefg") == 'a');
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn max(comptime T: type, slice: []const T) -> T {
|
pub fn max(comptime T: type, slice: []const T) T {
|
||||||
var best = slice[0];
|
var best = slice[0];
|
||||||
for (slice[1..]) |item| {
|
for (slice[1..]) |item| {
|
||||||
best = math.max(best, item);
|
best = math.max(best, item);
|
||||||
@ -548,14 +548,14 @@ test "mem.max" {
|
|||||||
assert(max(u8, "abcdefg") == 'g');
|
assert(max(u8, "abcdefg") == 'g');
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn swap(comptime T: type, a: &T, b: &T) {
|
pub fn swap(comptime T: type, a: &T, b: &T) void {
|
||||||
const tmp = *a;
|
const tmp = *a;
|
||||||
*a = *b;
|
*a = *b;
|
||||||
*b = tmp;
|
*b = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// In-place order reversal of a slice
|
/// In-place order reversal of a slice
|
||||||
pub fn reverse(comptime T: type, items: []T) {
|
pub fn reverse(comptime T: type, items: []T) void {
|
||||||
var i: usize = 0;
|
var i: usize = 0;
|
||||||
const end = items.len / 2;
|
const end = items.len / 2;
|
||||||
while (i < end) : (i += 1) {
|
while (i < end) : (i += 1) {
|
||||||
@ -572,7 +572,7 @@ test "std.mem.reverse" {
|
|||||||
|
|
||||||
/// In-place rotation of the values in an array ([0 1 2 3] becomes [1 2 3 0] if we rotate by 1)
|
/// In-place rotation of the values in an array ([0 1 2 3] becomes [1 2 3 0] if we rotate by 1)
|
||||||
/// Assumes 0 <= amount <= items.len
|
/// Assumes 0 <= amount <= items.len
|
||||||
pub fn rotate(comptime T: type, items: []T, amount: usize) {
|
pub fn rotate(comptime T: type, items: []T, amount: usize) void {
|
||||||
reverse(T, items[0..amount]);
|
reverse(T, items[0..amount]);
|
||||||
reverse(T, items[amount..]);
|
reverse(T, items[amount..]);
|
||||||
reverse(T, items);
|
reverse(T, items);
|
||||||
|
20
std/net.zig
20
std/net.zig
@ -17,7 +17,7 @@ error BadFd;
|
|||||||
const Connection = struct {
|
const Connection = struct {
|
||||||
socket_fd: i32,
|
socket_fd: i32,
|
||||||
|
|
||||||
pub fn send(c: Connection, buf: []const u8) -> %usize {
|
pub fn send(c: Connection, buf: []const u8) %usize {
|
||||||
const send_ret = linux.sendto(c.socket_fd, buf.ptr, buf.len, 0, null, 0);
|
const send_ret = linux.sendto(c.socket_fd, buf.ptr, buf.len, 0, null, 0);
|
||||||
const send_err = linux.getErrno(send_ret);
|
const send_err = linux.getErrno(send_ret);
|
||||||
switch (send_err) {
|
switch (send_err) {
|
||||||
@ -31,7 +31,7 @@ const Connection = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn recv(c: Connection, buf: []u8) -> %[]u8 {
|
pub fn recv(c: Connection, buf: []u8) %[]u8 {
|
||||||
const recv_ret = linux.recvfrom(c.socket_fd, buf.ptr, buf.len, 0, null, null);
|
const recv_ret = linux.recvfrom(c.socket_fd, buf.ptr, buf.len, 0, null, null);
|
||||||
const recv_err = linux.getErrno(recv_ret);
|
const recv_err = linux.getErrno(recv_ret);
|
||||||
switch (recv_err) {
|
switch (recv_err) {
|
||||||
@ -48,7 +48,7 @@ const Connection = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn close(c: Connection) -> %void {
|
pub fn close(c: Connection) %void {
|
||||||
switch (linux.getErrno(linux.close(c.socket_fd))) {
|
switch (linux.getErrno(linux.close(c.socket_fd))) {
|
||||||
0 => return,
|
0 => return,
|
||||||
linux.EBADF => unreachable,
|
linux.EBADF => unreachable,
|
||||||
@ -66,7 +66,7 @@ const Address = struct {
|
|||||||
sort_key: i32,
|
sort_key: i32,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn lookup(hostname: []const u8, out_addrs: []Address) -> %[]Address {
|
pub fn lookup(hostname: []const u8, out_addrs: []Address) %[]Address {
|
||||||
if (hostname.len == 0) {
|
if (hostname.len == 0) {
|
||||||
|
|
||||||
unreachable; // TODO
|
unreachable; // TODO
|
||||||
@ -75,7 +75,7 @@ pub fn lookup(hostname: []const u8, out_addrs: []Address) -> %[]Address {
|
|||||||
unreachable; // TODO
|
unreachable; // TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn connectAddr(addr: &Address, port: u16) -> %Connection {
|
pub fn connectAddr(addr: &Address, port: u16) %Connection {
|
||||||
const socket_ret = linux.socket(addr.family, linux.SOCK_STREAM, linux.PROTO_tcp);
|
const socket_ret = linux.socket(addr.family, linux.SOCK_STREAM, linux.PROTO_tcp);
|
||||||
const socket_err = linux.getErrno(socket_ret);
|
const socket_err = linux.getErrno(socket_ret);
|
||||||
if (socket_err > 0) {
|
if (socket_err > 0) {
|
||||||
@ -118,7 +118,7 @@ pub fn connectAddr(addr: &Address, port: u16) -> %Connection {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn connect(hostname: []const u8, port: u16) -> %Connection {
|
pub fn connect(hostname: []const u8, port: u16) %Connection {
|
||||||
var addrs_buf: [1]Address = undefined;
|
var addrs_buf: [1]Address = undefined;
|
||||||
const addrs_slice = try lookup(hostname, addrs_buf[0..]);
|
const addrs_slice = try lookup(hostname, addrs_buf[0..]);
|
||||||
const main_addr = &addrs_slice[0];
|
const main_addr = &addrs_slice[0];
|
||||||
@ -128,12 +128,12 @@ pub fn connect(hostname: []const u8, port: u16) -> %Connection {
|
|||||||
|
|
||||||
error InvalidIpLiteral;
|
error InvalidIpLiteral;
|
||||||
|
|
||||||
pub fn parseIpLiteral(buf: []const u8) -> %Address {
|
pub fn parseIpLiteral(buf: []const u8) %Address {
|
||||||
|
|
||||||
return error.InvalidIpLiteral;
|
return error.InvalidIpLiteral;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hexDigit(c: u8) -> u8 {
|
fn hexDigit(c: u8) u8 {
|
||||||
// TODO use switch with range
|
// TODO use switch with range
|
||||||
if ('0' <= c and c <= '9') {
|
if ('0' <= c and c <= '9') {
|
||||||
return c - '0';
|
return c - '0';
|
||||||
@ -151,7 +151,7 @@ error Overflow;
|
|||||||
error JunkAtEnd;
|
error JunkAtEnd;
|
||||||
error Incomplete;
|
error Incomplete;
|
||||||
|
|
||||||
fn parseIp6(buf: []const u8) -> %Address {
|
fn parseIp6(buf: []const u8) %Address {
|
||||||
var result: Address = undefined;
|
var result: Address = undefined;
|
||||||
result.family = linux.AF_INET6;
|
result.family = linux.AF_INET6;
|
||||||
result.scope_id = 0;
|
result.scope_id = 0;
|
||||||
@ -232,7 +232,7 @@ fn parseIp6(buf: []const u8) -> %Address {
|
|||||||
return error.Incomplete;
|
return error.Incomplete;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parseIp4(buf: []const u8) -> %u32 {
|
fn parseIp4(buf: []const u8) %u32 {
|
||||||
var result: u32 = undefined;
|
var result: u32 = undefined;
|
||||||
const out_ptr = ([]u8)((&result)[0..1]);
|
const out_ptr = ([]u8)((&result)[0..1]);
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user