Skip to content

Commit

Permalink
rewrite + bugfix
Browse files Browse the repository at this point in the history
  • Loading branch information
jackdotink committed Oct 4, 2023
1 parent 6ac84db commit 7628101
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 39 deletions.
103 changes: 65 additions & 38 deletions libs/Future/Future.luau
Original file line number Diff line number Diff line change
@@ -1,79 +1,65 @@
local Spawn = require(script.Parent.Spawn)

local Future = {}
Future.__index = Future
export type Future<T...> = {
ValueList: { any }?,
AfterList: { (T...) -> () },
YieldList: { thread },

function Future.new<T..., A...>(Callback: (A...) -> T..., ...: A...)
local self = setmetatable({}, Future)
IsComplete: (self: Future<T...>) -> boolean,
IsPending: (self: Future<T...>) -> boolean,

self.ValueList = nil :: { any }?
Expect: (self: Future<T...>, Message: string) -> T...,
Unwrap: (self: Future<T...>) -> T...,
UnwrapOr: (self: Future<T...>, T...) -> T...,
UnwrapOrElse: (self: Future<T...>, Else: () -> T...) -> T...,

self.AfterList = {} :: { (T...) -> () }
self.YieldList = {} :: { thread }
After: (self: Future<T...>, Callback: (T...) -> ()) -> (),
Await: (self: Future<T...>) -> T...,
}

task.spawn(function(self, ...)
self.ValueList = { Callback(...) }

for _, Thread in self.YieldList do
task.spawn(Thread, table.unpack(self.ValueList))
end

for _, Callback in self.AfterList do
Spawn(Callback, table.unpack(self.ValueList))
end
end, self, ...)

return self
end

export type Future<T...> = typeof(Future.new(function(): T... end))

function Future.Try<T..., A...>(Callback: (A...) -> T..., ...: A...)
return Future.new(pcall, Callback, ...)
end

function Future.IsComplete<T...>(self: Future<T...>)
local function IsComplete<T...>(self: Future<T...>): boolean
return self.ValueList ~= nil
end

function Future.IsPending<T...>(self: Future<T...>)
local function IsPending<T...>(self: Future<T...>): boolean
return self.ValueList == nil
end

function Future.Expect<T...>(self: Future<T...>, Message: string): T...
local function Expect<T...>(self: Future<T...>, Message: string): T...
assert(self.ValueList, Message)

return table.unpack(self.ValueList)
end

function Future.Unwrap<T...>(self: Future<T...>): T...
return self:Expect("Attempt to unwrap pending value!")
local function Unwrap<T...>(self: Future<T...>): T...
return self:Expect("Attempt to unwrap pending future!")
end

function Future.UnwrapOr<T...>(self: Future<T...>, ...: T...)
local function UnwrapOr<T...>(self: Future<T...>, ...): T...
if self.ValueList then
return table.unpack(self.ValueList)
else
return ...
end
end

function Future.UnwrapOrElse<T...>(self: Future<T...>, Else: () -> T...)
local function UnwrapOrElse<T...>(self: Future<T...>, Else: () -> T...): T...
if self.ValueList then
return table.unpack(self.ValueList)
else
return Else()
end
end

function Future.After<T...>(self: Future<T...>, Callback: (T...) -> ())
local function After<T...>(self: Future<T...>, Callback: (T...) -> ()): T...
if self.ValueList then
Spawn(Callback, table.unpack(self.ValueList))
else
table.insert(self.AfterList, Callback)
end
end

function Future.Await<T...>(self: Future<T...>): T...
local function Await<T...>(self: Future<T...>): T...
if self.ValueList then
return table.unpack(self.ValueList)
else
Expand All @@ -83,4 +69,45 @@ function Future.Await<T...>(self: Future<T...>): T...
end
end

return Future
local function Future<T..., A...>(Callback: (A...) -> T..., ...: A...): Future<T...>
local self: Future<T...> = {
ValueList = nil,
AfterList = {},
YieldList = {},

IsComplete = IsComplete,
IsPending = IsPending,

Expect = Expect,
Unwrap = Unwrap,
UnwrapOr = UnwrapOr,
UnwrapOrElse = UnwrapOrElse,

After = After,
Await = Await,
} :: any

Spawn(function(self: Future<T...>, Callback: (A...) -> T..., ...: A...)
local ValueList = { Callback(...) }
self.ValueList = ValueList

for _, Thread in self.YieldList do
task.spawn(Thread, table.unpack(ValueList))
end

for _, Callback in self.AfterList do
Spawn(Callback, table.unpack(ValueList))
end
end, self, Callback, ...)

return self
end

local function Try<T..., A...>(Callback: (A...) -> T..., ...: A...): Future<(boolean, T...)>
return Future(pcall, Callback, ...)
end

return {
new = Future,
Try = Try,
}
2 changes: 1 addition & 1 deletion libs/Future/wally.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "red-blox/future"
version = "1.0.0"
version = "1.0.1"
registry = "https://github.com/UpliftGames/wally-index"
realm = "shared"

Expand Down

0 comments on commit 7628101

Please sign in to comment.