I haven’t written any zig yet. One thing I’m curious about regarding allocators being explicitly passed in: is that by convention, or language enforced?
Cool, thanks for that.By convention.
See this topic on Zig's forum.
unwrap()
and the try operator. They are convenient when writing new code and I don't yet want to have to think about all possible error cases. But I want to handle those properly at some point, so I can use the linter to check for those usages and replace them with robust error handling.cat main.zig
const std = @import("std");
const deb = std.debug;
const io = std.io;
const pri = deb.print;
const stdoutf = io.getStdOut().writer();
var bw = io.bufferedWriter(stdoutf);
const stdout = bw.writer();
const arrayList = std.ArrayList;
const sheap = std.heap;
const config=.{.safety=true};
var gpa = sheap.GeneralPurposeAllocator(config){};
const gpaallocator = gpa.allocator();
const Vec = struct {
x: f32,
y: f32,
pub fn init(xa:f32,ya:f32) Vec {
return Vec { .x=xa + 0.1 , .y=ya + 0.2};
}
pub fn printx(v:Vec) void {
pri("{e}\n",.{v.x});
}
};
const Month = enum {
January,
February,
March,
};
fn myadd(a:i32,b:i32) i32 {
return a+b;
}
fn myprint(s:[] const u8) void {
pri("string:{s}",.{s});
}
pub fn range(len: usize) []const u0 {
return @as([*]u0, undefined)[0..len];
}
const myunion = union(enum) {
i:i32,
f:f32,
};
fn printunion(u:myunion) void {
switch(u) {
.i => |i| pri("Integer : {d}\n",.{i}),
.f => |f| pri("Float : {e}\n",.{f}),
}
}
const myerrors= error { MyError,MyError2};
fn testerror(succeed:bool) myerrors!bool {
if(!succeed) {
return myerrors.MyError;
}
else {
return true;
}
}
pub fn main() !void {
var arrx:[10]u32=undefined;
arrx[2]=4;
pri("{d}\n",.{arrx[2]});
var x: i32=321;
var px: *i32=&x;
pri("{d}\n",.{px.*});
var ov: ?u32=null;
if(ov)|value|{
pri("Value : {d}\n",.{value});
}
else {
pri("isnull\n",.{});
}
ov=88;
if(ov)|value|{
pri("Value : {d}\n",.{value});
}
else {
pri("isnull\n",.{});
}
const r:bool = testerror(false) catch |err| blk: {
if (err == myerrors.MyError) {
break :blk false;
}
else {
return;
}
};
pri("{any}\n",.{r});
switch (15) {
0...10 => pri{"0-10\n",.{}},
15 => pri("15\n",.{}),
20 => pri("20\n",.{}),
else => pri("Error\n",.{}),
}
pri("Hello World1\n", .{});
try stdout.print("Hello World2\n", .{});
try bw.flush();
const myvec = Vec.init(2.0,3.0);
pri("{e}\n", .{myvec.x});
myvec.printx();
var vv: i32 = 123;
pri("{d}\n", .{vv});
var month:Month=.January;
pri("Month:{}\n",.{month});
pri("Add : {d}\n", .{myadd(123,456)});
myprint("Mystring\n");
const m1:myunion=myunion{.f=2.3};
const m2:myunion=myunion{.i=5};
printunion(m1);
printunion(m2);
var list = arrayList(u8).init(gpaallocator);
defer list.deinit();
try list.append('C');
try list.append('A');
try list.append('T');
_ =list.pop();
for (list.toOwnedSlice()) |elem,index| {
pri("by val: {d} : {c} \n", .{index,elem});
}
A bosh like that can easily be written in any lang regardless of whether $lang is "good"/"bad", "popular"/"unpopular", "modern"/"ancient" and so on. Where did you find those mussy exercises?How zig looks like
Nope, it is much more useful to learn FORTH.Sounds like it is more useful to learn COBOL
fn enableEventSource(self: *EventQueue, es: *EventSource, ek: EventKind) !void {
const FdAlreadyInSet = os.EpollCtlError.FileDescriptorAlreadyPresentInSet;
var em: u32 = if (.can_read == ek) (EPOLL.IN | EPOLL.RDHUP) else EPOLL.OUT;
em |= EPOLL.ONESHOT;
var ee = EpollEvent {
.events = em,
.data = EpollData{.ptr = @ptrToInt(es)},
};
// emulate FreeBSD kqueue behavior
epollCtl(self.fd, EPOLL.CTL_ADD, es.id, &ee) catch |err| {
return switch (err) {
FdAlreadyInSet => try epollCtl(self.fd, EPOLL.CTL_MOD, es.id, &ee),
else => err,
};
};
}
I converted the website to a pdf using "pandoc".A bosh like that can easily be written in any lang regardless of whether $lang is "good"/"bad", "popular"/"unpopular", "modern"/"ancient" and so on. Where did you find those mussy exercises?![]()
pandoc is really cool tool, but have you ever tried to implement a c-compiler/os-kernel in Haskell?..I converted the website to a pdf using "pandoc".
Now that's a name I've not heard in a long time. A long time. Instead of adding Rust (or Zig) to base, let's rewrite the kernel and utilities in Forth. Oh wait, BTDT, got the T-shirt. I vaguely remember having an EPROM (or was it a tape?) that allowed booting Forth on a 6809-based microcomputer. It was sort of fun.Nope, it is much more useful to learn FORTH.
I vaguely remember having an EPROM (or was it a tape?) that allowed booting Forth on a 6809-based microcomputer. It was sort of fun.
Was. It was replaced with Lua.BTW, as far as I am aware FORTH is/was (?) used in FreeBSD boot-loader.
This is usually ends up being a mistake. Use well defined interfaces and separate assembly code in assembly files so that you can more easily target multiple architectures. inline assembly will make a port very painful.I’ve developed a way of working that includes a lot of inline assembly within C — something I find both expressive and necessary.
Wow. Wow. WHO IS STILL USING THAT‽ Although, I guess since the US gov. used (or is still using) 8in floppy disks, I wouldn't be surprised if someone was still using it.There is already a port! lang/algol68g
Ugh. Why do people STILL want to add random fadlangs to FreeBSD. While we're at it, let's add some old now-worthless languages too!.
That's not true. At the linking stage, machine code from different compilers and programming languages can be combined into a single binary. That's how there can be Rust code in the Linux kernel. And Zig interoperability with C works much better, because Zig can compile C natively, which can help avoid much of the increase in build system complexity that comes with integrating other "foreign" languages like Rust.If you want to switch to another language,
you'll have to rewrite everything,
which, you guessed right, would be nearly the same,
as writing a complete new OS from the very start.
C++, Zig, and even Rust are not slower than C. Rust might often make it less convenient to write fast software, but that is also true for C, in a very different way. In my experience, C often beats such benchmarks only because the code is highly manually optimized, with no regard for portability and readability. When comparing simple idiomatic implementations, it is C that often gets beaten if the other languages can benefit from relevant features that C lacks.after what I figured out from several blogs, and benchmarks (others made),
C still produces the fastest machine code.
For an OS, especially a kernel with multitasking, this is something quite important.
Some may even say #1 priority.
To an extent. But only if you stick to C linkage. This loses most of the power of more recent languages. For example a function returning a C++ std::string cannot be consumed from Zig.That's not true. At the linking stage, machine code from different compilers and programming languages can be combined into a single binary.
zig cc can but that is really just a re-badged clang compiler. Zig can kind of consume C directly without bindings but in a way, not quite as elegant as C++.And Zig interoperability with C works much better, because Zig can compile C natively
The general case of copying a std container or an array is slower in C++ because it needs to call the constructor (and destructor) on each element. You can't safely memcpy in most cases.C++, Zig, and even Rust are not slower than C.
The general case of copying a std container or an array is slower in C++ because it needs to call the constructor (and destructor) on each element. You can't safely memcpy in most cases.
So other than in constrained benchmark code dealing entirely with POD types; C++ is certainly slower than C.
Indeed. Perhaps the template system could be leveraged so that a common safe type (i.e vector<unsigned char>) has a concrete copy / insert / etc that is merely memcpy.C++ should have a function copy_array() that does that when the element class has constructor or destructor, and memcpy if not.