Skip to content

Commit

Permalink
Complete the foldFree function for FreeMonad
Browse files Browse the repository at this point in the history
* Add two Monad instance: MWriter and MWriterMaybe
* Add a Monoid instance of ArrayList
* Fix some memory leak issues when call foldFree
  • Loading branch information
flyfish30 committed Oct 9, 2024
1 parent 5ef48a4 commit cdf7e45
Show file tree
Hide file tree
Showing 7 changed files with 681 additions and 90 deletions.
13 changes: 13 additions & 0 deletions src/array_list_monad.zig
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,19 @@ pub const ArrayListMonadImpl = struct {
}
return mb;
}

pub fn join(
self: *Self,
comptime A: type,
mma: F(F(A)),
) MbType(A) {
var res_ma = ArrayList(A).init(self.allocator);
for (mma.items) |ma| {
if (ma.items.len > 0)
try res_ma.appendSlice(ma.items);
}
return res_ma;
}
};

// These functions are defined for unit test
Expand Down
82 changes: 82 additions & 0 deletions src/base.zig
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
//! All base types and functions for zig-cats
const std = @import("std");
const Allocator = std.mem.Allocator;

// pub usingnamespace @import("base_types.zig");

/// A single-argument type function for type constructor
pub const TCtor = *const fn (comptime type) type;
Expand Down Expand Up @@ -140,6 +143,16 @@ pub fn castInplaceValue(comptime T: type, val: anytype) T {
}
}

pub fn defaultVal(comptime T: type) T {
const info_a = @typeInfo(T);
if (info_a == .Fn) {
return getDefaultFn(T);
} else if (info_a == .Pointer and @typeInfo(std.meta.Child(T)) == .Fn) {
return getDefaultFn(std.meta.Child(T));
}
return std.mem.zeroes(T);
}

pub fn getDefaultFn(comptime Fn: type) fn (MapFnInType(Fn)) MapFnRetType(Fn) {
return struct {
const A = MapFnInType(Fn);
Expand Down Expand Up @@ -181,3 +194,72 @@ pub fn freeNothing(a: anytype) void {
_ = a;
return;
}

/// Clone a constructed data or referance a pointer
pub fn copyOrCloneOrRef(a: anytype) !@TypeOf(a) {
const T = @TypeOf(a);
const info = @typeInfo(T);
switch (info) {
.Struct, .Enum, .Union, .Opaque => {
if (@hasDecl(T, "clone")) {
return a.clone();
}
},
.Pointer => {
const Child = info.Pointer.child;
const c_info = @typeInfo(Child);
if (info.Pointer.size != .One) {
@compileError("deinitOrUnref only for pointer that has only one element!");
}
switch (c_info) {
.Struct, .Enum, .Union, .Opaque => {
if (@hasDecl(T, "strongRef")) {
return a.strongRef();
}
},
else => {},
}
},
else => {},
}

return a;
}

/// get a normal deinit or unreference function for free some memory
pub fn getDeinitOrUnref(comptime T: type) FreeTFn(T) {
return struct {
fn freeT(a: T) void {
deinitOrUnref(a);
}
}.freeT;
}

/// Deinit a constructed data or unreferance a pointer
pub fn deinitOrUnref(a: anytype) void {
const T = @TypeOf(a);
const info = @typeInfo(T);
switch (info) {
.Struct, .Enum, .Union, .Opaque => {
if (@hasDecl(T, "deinit")) {
a.deinit();
}
},
.Pointer => {
const Child = info.Pointer.child;
const c_info = @typeInfo(Child);
if (info.Pointer.size != .One) {
@compileError("deinitOrUnref only for pointer that has only one element!");
}
switch (c_info) {
.Struct, .Enum, .Union, .Opaque => {
if (@hasDecl(T, "strongUnref")) {
_ = a.strongUnref();
}
},
else => {},
}
},
else => {},
}
}
Loading

0 comments on commit cdf7e45

Please sign in to comment.