Recreated most of the demo code from talk

This commit is contained in:
nothke 2024-08-12 19:24:48 +02:00
parent 0730b9f6c4
commit 2030301fdb
5 changed files with 309 additions and 102 deletions

View File

@ -1,5 +1,7 @@
See [talk notes](talk.md)
[main.zig](src/main.zig) has most of the examples from the talk reconstructed.
To run `zig build run`
To build C samples, run:

View File

@ -8,12 +8,16 @@ public:
MyClass()
{
ptr = malloc(sizeof(100000000));
std::cout << "Allocating 1MB\n";
// Allocate 1MB for no reason:
ptr = malloc(sizeof(1000 * 1000));
}
~MyClass()
{
free(ptr);
std::cout << "Destroyed 1MB\n";
}
};
@ -21,7 +25,9 @@ MyClass myClass;
int main()
{
std::vector<MyClass> vec;
vec.push_back({});
// Trick question, how many times is it constructed and destroyed?
std::vector<MyClass> vecOfMyClasses;
vec.push_back(myClass);
vec.push_back(myClass);
}

View File

@ -1,43 +0,0 @@
const std = @import("std");
fn calc(a: i32) i32 {
return a;
}
const SOmethin = enum {
One,
Two,
Three,
};
fn Optional(comptime T: type) type {
return struct {
valid: bool,
value: T,
};
}
fn add(a: anytype, b: anytype) @TypeOf(a + b) {
return a + b;
}
const DivisionError = error{DivisionByZero};
fn divide(a: f32, b: f32) !f32 {
if (b == 0)
return DivisionError.DivisionByZero;
return a / b;
}
pub fn main() !void {
std.debug.print("All your {s} are belong to us.\n", .{"codebase"});
const vec = @Vector(4, i32){ 1, 0, 1, 0 };
const vec2 = @Vector(4, i32){ 0, 1, 0, 1 };
std.debug.print("vec: {}", .{vec + vec2});
}

View File

@ -1,114 +1,353 @@
const std = @import("std");
const Other = @import("other.zig");
// Struct
// const/var and integers
const Vector2D = packed struct {
x: i5 = 2,
y: i23,
fn demoIntegers() void {
const signedInt: i32 = -2345;
const unsignedInt: u32 = 34;
const signedChar: i8 = 4;
const unsignedShort: u16 = 5362;
fn name(self: Vector2D) void {
_ = self; // autofix
const sum = signedInt + unsignedInt + signedChar + unsignedShort;
}
var mutableInt = sum + 3;
mutableInt += sum;
fn init() void {}
fn deinit() void {}
};
// Casting from narrow to wide type is allowed
const arbitraryWidth: i2 = -1;
const widerType: i4 = arbitraryWidth;
_ = widerType; // autofix
// Functions
// Casting to a narrower type is resolved at compile-time here
const narrowerType: i3 = arbitraryWidth;
_ = narrowerType; // autofix
fn add(a: i32, b: i32) i32 {
return a + b;
// Casting from wide to narrow must be explicit with @intCast
var wide: i32 = 0;
wide = 345;
const narrow: u16 = @intCast(wide);
_ = narrow; // autofix
var overflow: u8 = 0;
//overflow -= 1; // This will cause an overflow error
overflow -%= 1; // ..But if we use +% or -% this is allow overflow operator
}
fn setTo3(a: *i32) void {
a.* = 3;
// Arrays
fn demoArrays() void {
const arr = [3]u32 {23, 45, 67};
// or: const arr = [_]u32 {23, 45, 67};
std.log.info("arr: {}", .{arr.len});
// You can initailize to zeroes like this:
var arr2 = std.mem.zeroes([16]u32);
arr2[0] = 3;
// 2 ways of getting slices:
const slice1: []u32 = &arr2; // Casting array pointer to slice
const slice2 = arr2[0..]; // Getting with range
// Multi-object for loops:
for (slice1, slice2) |v1, v2| {
if (v1 != v2)
std.log.err("Impossible!", .{});
}
}
// Error unions
// Structs
const DivideError = error{
DivivisionError,
const Vector2D = struct {
x: f32 = 0, // default initialized
y: f32 = 0,
};
fn divide(a: f32, b: f32) !f32 {
if (b == 0) {
return DivideError.DivivisionError;
} else {
return a / b;
fn demoStruct() void {
var uninitedVec: Vector2D = undefined; // Explicitly uninitialized
const initedVec: Vector2D = .{ .x = 0, .y = 0 }; // Explicitly initialized
const defaultInitedVec: Vector2D = .{ .x = 0, .y = 0 }; // Default initialized
uninitedVec.x = undefined; // Force it to be used
std.log.debug("uninitedVec: {}", .{uninitedVec});
std.log.debug("initedVec: {}", .{initedVec});
std.log.debug("defaultInited: {}", .{defaultInitedVec});
}
// Packed structs
const WindowFlags = packed struct {
windowed: bool = false,
maximized: bool = false,
autoResizeable: bool = false,
};
fn demoPackedStruct() void {
var flags = WindowFlags{};
flags.autoResizeable = true;
const maximizedPtr = &flags.maximized;
//@compileLog("bit pointer type is: ", @TypeOf(maximizedPtr));
std.log.info("bit pointer type is: {}", .{@TypeOf(maximizedPtr)});
}
// File is struct
fn demoFileIsStruct() void {
const Other = @import("other.zig");
const o = Other{ .member = 42 };
std.log.info("Other type: pi: {}, .member: {}", .{Other.pi, o.member});
}
// SIMD vectors
fn demoVectors() void {
const vec = @Vector(3, f32){3,2,1};
var vec2 = @Vector(3, f32){1,2,3};
const vec3 = vec + vec2;
std.log.info("vec sum is: {}", .{vec3});
// index
vec2[0] = 3;
// loop through by casting to array
var vec2arr: [3]f32 = vec2;
for (&vec2arr) |*f| {
f.* = 12.4;
}
vec2 = vec2arr;
}
// Comptime generics
fn Optional(comptime T: type) type {
return struct {
exists: bool = false,
value: T,
exists: bool,
};
}
fn demoComptimeGenerics() void {
const optInt = Optional(i32){
.exists = true,
.value = 5,
};
const optVector2D = Optional(Vector2D){
.exists = true,
.value = .{ .x = 1, .y = 2 },
};
std.log.info("opt int value: {}, vec value: {}", .{optInt.value, optVector2D.value});
}
// anytype
fn add(a: anytype, b: anytype) @TypeOf(a + b) {
return a + b;
}
fn demoAnytype() void {
std.log.info("- DEMO: anytype", .{});
const a = add(3, 2); // will be comptime_int
std.log.info("add integers: {}, type: {}", .{a, @TypeOf(a)});
const f = add(34.32, 1.3); // will be comptime_float
std.log.info("add floats: {}, type: {}", .{f, @TypeOf(f)});
const f2 = add(@as(f32, 34.32), 1.3); // will be f32
std.log.info("add floats: {}, type: {}", .{f2, @TypeOf(f2)});
var f3: f32 = 0;
f3 = add(2.3, 1.3); // will be f32
std.log.info("add floats: {}, type: {}", .{f3, @TypeOf(f3)});
}
// Error unions
const DivisionError = error {
DivideByZero,
};
fn divide(a: f32, b: f32) !f32 {
if (b == 0) {
return DivisionError.DivideByZero;
} else {
return a / b;
}
}
fn demoErrorUnions() !void {
const result1 = try divide(6, 2); // No error
const result2 = divide(4, 0) catch 0; // Error! Explicitly catch with 0
// Get the value and handle each error:
if (divide(3, 0)) |value| {
std.log.info("The value is: {}", .{value});
}
else |err| switch (err) {
error.DivideByZero => std.log.debug("Oh no, it's division by zero!", .{}),
}
std.log.debug("{} {}", .{result1, result2});
}
// Optionals
fn demoOptionals() void {
var vec: ?Vector2D = null;
if (vec) |vecValue| {
std.log.info("vec: {}", .{vecValue});
}
vec = .{.x = 4, .y = 3};
if (vec) |vecValue| {
std.log.info("vec: {}", .{vecValue});
}
const otherVec = vec orelse Vector2D{}; // if null, set to default
std.log.info("vec: {}", .{otherVec});
var num: i32 = 3;
var optionalPointer: ?*i32 = null; // Optional pointers take no extra space
optionalPointer = &num;
optionalPointer.?.* = 5; // Set optional pointer value
}
// Tagged unions
const Person = struct {
const Human = struct {
name: []const u8,
// an example of "polymorphic" function that all types have:
fn say() void {
std.log.info("Yo!", .{});
}
};
const Horse = struct {
canRide: bool = false,
rider: ?*const Person = null,
rider: ?*const Human = null,
fn say() void {
std.log.info("Njiiiii!", .{});
}
};
const Duck = struct {
friend: ?*Animal = null,
gone: bool = false,
friend: ?*Animal = null, // only ducks can have friends!
fn say() void {
std.log.info("Quack!", .{});
}
};
const AnimalType = enum {
Horse,
Duck,
Person,
Human,
};
const Animal = union(AnimalType) {
Horse: Horse,
Duck: Duck,
Person: Person,
Human: Human,
fn say(self: Animal) void {
switch (self) {
inline else => |case| @TypeOf(case).say(),
}
// ^ this, is equivalent to this:
// switch (self) {
// .Horse => Horse.say(),
// .Human => Human.say(),
// .Duck => Duck.say(),
// }
}
};
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const alloc = gpa.allocator();
defer _ = gpa.deinit();
fn demoTaggedUnions() void {
var horseAnimal = Animal{ .Horse = .{} };
var list = std.ArrayList(i32).init(alloc);
defer list.deinit();
try list.append(324);
try list.append(456);
const person = Human{ .name = "Ivan" };
for (list.items) |item| {
std.log.debug("item: {}", .{item});
// You can check which animal it is in if:
if (horseAnimal == .Horse) {
horseAnimal.Horse.rider = &person;
}
var animal = Animal{ .Horse = .{ .canRide = true } };
// or switch:
const person = Person{ .name = "Dragutin" };
if (animal == .Horse) {
animal.Horse.rider = &person;
}
switch (animal) {
switch (horseAnimal) {
.Horse => |*horse| horse.rider = &person,
else => {},
}
var personAnimal = Animal{ .Person = .{ .name = "Aleksa" } };
var personAnimal = Animal{ .Human = .{ .name = "Hugo" } };
var duck = Duck{ .friend = &personAnimal };
const duck = Duck{ .friend = &personAnimal };
duck.gone = true;
std.log.debug("Rider name: {s}", .{if (horseAnimal.Horse.rider) |rider| rider.name else "none"});
std.log.debug("Rider name: {s}", .{if (animal.Horse.rider) |rider| rider.name else "none"});
@TypeOf(duck).say();
horseAnimal.say();
}
// Allocators
fn demoAllocators() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const alloc = gpa.allocator();
defer _ = gpa.deinit();
// Uncomment these lines to use stack memory instead:
// var buffer: [1024]u8 = undefined;
// var fba = std.heap.FixedBufferAllocator.init(&buffer);
// const alloc = fba.allocator();
var list = std.ArrayList(i32).init(alloc);
defer list.deinit(); // Comment this line and see the gpa fail
try list.append(3);
try list.append(456);
try list.append(656);
for (list.items, 0..) |item, i| {
std.log.info("item {}: {}", .{i, item});
}
}
pub fn main() !void {
std.debug.print("All your {s} are belong to us.\n", .{"codebase"});
demoIntegers();
demoArrays();
demoStruct();
demoPackedStruct();
demoFileIsStruct();
demoVectors();
demoComptimeGenerics();
demoAnytype();
try demoErrorUnions(); // Errors propagate up so we need to try
demoOptionals();
demoTaggedUnions();
try demoAllocators();
}

View File

@ -1,9 +1,12 @@
const main = @import("main.zig");
member: i32,
// Must be pub to be available to other files
pub const pi = 3.14;
pub fn add() i32 {
pub fn infiniteLoop() i32 {
try main.main();
return 3;
return 0;
}