Recreated most of the demo code from talk
This commit is contained in:
parent
0730b9f6c4
commit
2030301fdb
@ -1,5 +1,7 @@
|
|||||||
See [talk notes](talk.md)
|
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 run `zig build run`
|
||||||
|
|
||||||
To build C samples, run:
|
To build C samples, run:
|
||||||
|
12
c/raii.cpp
12
c/raii.cpp
@ -8,12 +8,16 @@ public:
|
|||||||
|
|
||||||
MyClass()
|
MyClass()
|
||||||
{
|
{
|
||||||
ptr = malloc(sizeof(100000000));
|
std::cout << "Allocating 1MB\n";
|
||||||
|
|
||||||
|
// Allocate 1MB for no reason:
|
||||||
|
ptr = malloc(sizeof(1000 * 1000));
|
||||||
}
|
}
|
||||||
|
|
||||||
~MyClass()
|
~MyClass()
|
||||||
{
|
{
|
||||||
free(ptr);
|
free(ptr);
|
||||||
|
std::cout << "Destroyed 1MB\n";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -21,7 +25,9 @@ MyClass myClass;
|
|||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
std::vector<MyClass> vec;
|
// Trick question, how many times is it constructed and destroyed?
|
||||||
vec.push_back({});
|
|
||||||
|
|
||||||
|
std::vector<MyClass> vecOfMyClasses;
|
||||||
|
vec.push_back(myClass);
|
||||||
|
vec.push_back(myClass);
|
||||||
}
|
}
|
@ -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});
|
|
||||||
}
|
|
347
src/main.zig
347
src/main.zig
@ -1,114 +1,353 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const Other = @import("other.zig");
|
|
||||||
|
|
||||||
// Struct
|
// const/var and integers
|
||||||
|
|
||||||
const Vector2D = packed struct {
|
fn demoIntegers() void {
|
||||||
x: i5 = 2,
|
const signedInt: i32 = -2345;
|
||||||
y: i23,
|
const unsignedInt: u32 = 34;
|
||||||
|
const signedChar: i8 = 4;
|
||||||
|
const unsignedShort: u16 = 5362;
|
||||||
|
|
||||||
|
const sum = signedInt + unsignedInt + signedChar + unsignedShort;
|
||||||
|
|
||||||
fn name(self: Vector2D) void {
|
var mutableInt = sum + 3;
|
||||||
_ = self; // autofix
|
mutableInt += sum;
|
||||||
|
|
||||||
}
|
// Casting from narrow to wide type is allowed
|
||||||
|
const arbitraryWidth: i2 = -1;
|
||||||
|
const widerType: i4 = arbitraryWidth;
|
||||||
|
_ = widerType; // autofix
|
||||||
|
|
||||||
fn init() void {}
|
// Casting to a narrower type is resolved at compile-time here
|
||||||
fn deinit() void {}
|
const narrowerType: i3 = arbitraryWidth;
|
||||||
};
|
_ = narrowerType; // autofix
|
||||||
|
|
||||||
// Functions
|
// Casting from wide to narrow must be explicit with @intCast
|
||||||
|
var wide: i32 = 0;
|
||||||
|
wide = 345;
|
||||||
|
const narrow: u16 = @intCast(wide);
|
||||||
|
_ = narrow; // autofix
|
||||||
|
|
||||||
fn add(a: i32, b: i32) i32 {
|
var overflow: u8 = 0;
|
||||||
return a + b;
|
//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 {
|
// Arrays
|
||||||
a.* = 3;
|
|
||||||
|
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{
|
const Vector2D = struct {
|
||||||
DivivisionError,
|
x: f32 = 0, // default initialized
|
||||||
|
y: f32 = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn divide(a: f32, b: f32) !f32 {
|
fn demoStruct() void {
|
||||||
if (b == 0) {
|
var uninitedVec: Vector2D = undefined; // Explicitly uninitialized
|
||||||
return DivideError.DivivisionError;
|
const initedVec: Vector2D = .{ .x = 0, .y = 0 }; // Explicitly initialized
|
||||||
} else {
|
const defaultInitedVec: Vector2D = .{ .x = 0, .y = 0 }; // Default initialized
|
||||||
return a / b;
|
|
||||||
|
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
|
// Comptime generics
|
||||||
|
|
||||||
fn Optional(comptime T: type) type {
|
fn Optional(comptime T: type) type {
|
||||||
return struct {
|
return struct {
|
||||||
|
exists: bool = false,
|
||||||
value: T,
|
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 = #
|
||||||
|
optionalPointer.?.* = 5; // Set optional pointer value
|
||||||
|
}
|
||||||
|
|
||||||
// Tagged unions
|
// Tagged unions
|
||||||
|
|
||||||
const Person = struct {
|
const Human = struct {
|
||||||
name: []const u8,
|
name: []const u8,
|
||||||
|
|
||||||
|
// an example of "polymorphic" function that all types have:
|
||||||
|
fn say() void {
|
||||||
|
std.log.info("Yo!", .{});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const Horse = struct {
|
const Horse = struct {
|
||||||
canRide: bool = false,
|
rider: ?*const Human = null,
|
||||||
rider: ?*const Person = null,
|
|
||||||
|
fn say() void {
|
||||||
|
std.log.info("Njiiiii!", .{});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const Duck = struct {
|
const Duck = struct {
|
||||||
friend: ?*Animal = null,
|
friend: ?*Animal = null, // only ducks can have friends!
|
||||||
gone: bool = false,
|
|
||||||
|
fn say() void {
|
||||||
|
std.log.info("Quack!", .{});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const AnimalType = enum {
|
const AnimalType = enum {
|
||||||
Horse,
|
Horse,
|
||||||
Duck,
|
Duck,
|
||||||
Person,
|
Human,
|
||||||
};
|
};
|
||||||
|
|
||||||
const Animal = union(AnimalType) {
|
const Animal = union(AnimalType) {
|
||||||
Horse: Horse,
|
Horse: Horse,
|
||||||
Duck: Duck,
|
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 {
|
fn demoTaggedUnions() void {
|
||||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
var horseAnimal = Animal{ .Horse = .{} };
|
||||||
const alloc = gpa.allocator();
|
|
||||||
defer _ = gpa.deinit();
|
|
||||||
|
|
||||||
var list = std.ArrayList(i32).init(alloc);
|
const person = Human{ .name = "Ivan" };
|
||||||
defer list.deinit();
|
|
||||||
try list.append(324);
|
|
||||||
try list.append(456);
|
|
||||||
|
|
||||||
for (list.items) |item| {
|
// You can check which animal it is in if:
|
||||||
std.log.debug("item: {}", .{item});
|
|
||||||
|
if (horseAnimal == .Horse) {
|
||||||
|
horseAnimal.Horse.rider = &person;
|
||||||
}
|
}
|
||||||
|
|
||||||
var animal = Animal{ .Horse = .{ .canRide = true } };
|
// or switch:
|
||||||
|
|
||||||
const person = Person{ .name = "Dragutin" };
|
switch (horseAnimal) {
|
||||||
|
|
||||||
if (animal == .Horse) {
|
|
||||||
animal.Horse.rider = &person;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (animal) {
|
|
||||||
.Horse => |*horse| horse.rider = &person,
|
.Horse => |*horse| horse.rider = &person,
|
||||||
else => {},
|
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();
|
||||||
|
}
|
@ -1,9 +1,12 @@
|
|||||||
const main = @import("main.zig");
|
const main = @import("main.zig");
|
||||||
|
|
||||||
|
member: i32,
|
||||||
|
|
||||||
|
// Must be pub to be available to other files
|
||||||
pub const pi = 3.14;
|
pub const pi = 3.14;
|
||||||
|
|
||||||
pub fn add() i32 {
|
pub fn infiniteLoop() i32 {
|
||||||
try main.main();
|
try main.main();
|
||||||
|
|
||||||
return 3;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user