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)
|
||||
|
||||
[main.zig](src/main.zig) has most of the examples from the talk reconstructed.
|
||||
|
||||
To run `zig build run`
|
||||
|
||||
To build C samples, run:
|
||||
|
12
c/raii.cpp
12
c/raii.cpp
@ -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);
|
||||
}
|
@ -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 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 = #
|
||||
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();
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user