Last active
June 28, 2021 14:07
-
-
Save kurapica/76bbe39835ffc9aac9ac09287c7981ea to your computer and use it in GitHub Desktop.
PLoop-Switcher
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require "PLoop" (function(_ENV) | |
__Sealed__() | |
struct "Case" (function(_ENV) | |
import "System.Text" | |
export { unpack = unpack or table.unpack } | |
member "vars" { type = Variables, require = true } | |
member "func" { type = Callable, require = true } | |
-- Auto gen | |
member "min" { type = Number } | |
member "max" { type = Number } | |
member "validate" { type = Function } | |
member "process" { type = Function } | |
_ValTemplate = TemplateString[[ | |
return function( | |
@for i = 1, count do | |
var@i @(i < count and "," or "") | |
@end | |
) | |
return function( | |
@for i = 1, count do | |
arg@i @(i < count and "," or "") | |
@end | |
) | |
local ret, msg | |
@for i = 1, count do | |
local var = var@i | |
if arg@i ~= null then | |
ret, msg = var.validate(var.type, arg@i, true) | |
if msg then return false end | |
elseif not var.optional then | |
return false | |
end | |
@end | |
return true | |
end | |
end | |
]] | |
_ValVargsTemplate = TemplateString[[ | |
return function( | |
@for i = 1, count do | |
var@i @(i < count and "," or "") | |
@end | |
) | |
return function( | |
@for i = 1, count - 1 do | |
arg@i, | |
@end | |
... | |
) | |
local ret, msg | |
@for i = 1, count - 1 do | |
local var = var@i | |
if arg@i ~= null then | |
ret, msg = var.validate(var.type, arg@i, true) | |
if msg then return false end | |
elseif not var.optional then | |
return false | |
end | |
@end | |
local var = var@count | |
for i = 1, select("#", ...) do | |
local val = select(i, ...) | |
if val ~= null then | |
ret, msg = var.validate(var.type, val, true) | |
if msg then return false end | |
elseif i < var.mincount then | |
return false | |
end | |
end | |
return true | |
end | |
end | |
]] | |
_PassTemplate = TemplateString[[ | |
return function( | |
@for i = 1, count do | |
var@i @(i < count and "," or "") | |
@end | |
) | |
return function( | |
@for i = 1, count do | |
arg@i @(i < count and "," or "") | |
@end | |
) | |
@for i = 1, count do | |
local var = var@i | |
if arg@i ~= null then | |
if not var.immutable then | |
arg@i = var.validate(var.type, arg@i) | |
end | |
else | |
arg@i = var.default | |
end | |
@end | |
return | |
@for i = 1, count do | |
arg@i @(i < count and "," or "") | |
@end | |
end | |
end | |
]] | |
_PassVargsTemplate = TemplateString[[ | |
return function( | |
@for i = 1, count do | |
var@i @(i < count and "," or "") | |
@end | |
) | |
return function( | |
@for i = 1, count - 1 do | |
arg@i, | |
@end | |
... | |
) | |
@for i = 1, count - 1 do | |
local var = var@i | |
if arg@i ~= null then | |
if not var.immutable then | |
arg@i = var.validate(var.type, arg@i) | |
end | |
else | |
arg@i = var.default | |
end | |
@end | |
local var = var@count | |
if var.immutable then | |
return | |
@for i = 1, count - 1 do | |
arg@i, | |
@end | |
... | |
else | |
local rets = { ... } | |
for i, v in ipairs(rets) do | |
if v ~= null then | |
v = var.validate(var.type, v) | |
end | |
rets[i] = v | |
end | |
return | |
@for i = 1, count - 1 do | |
arg@i, | |
@end | |
unpack(rets) | |
end | |
end | |
end | |
]] | |
_AutoValidGen = setmetatable( { [0] = function() return true end }, { | |
__index = function(self, count) | |
local func = Toolset.loadsnippet(_ValTemplate{ count = count }, "Case_Val_" .. count, _ENV)() | |
rawset(self, count, func) | |
return func | |
end | |
}) | |
_AutoValidVargGen = setmetatable({}, { | |
__index = function(self, count) | |
local func = Toolset.loadsnippet(_ValVargsTemplate{ count = count }, "Case_VargsVal_" .. count, _ENV)() | |
rawset(self, count, func) | |
return func | |
end | |
}) | |
_AutoPassGen = setmetatable( { [0] = function() return end }, { | |
__index = function(self, count) | |
local func = Toolset.loadsnippet(_PassTemplate{ count = count }, "Case_Pass_" .. count, _ENV)() | |
rawset(self, count, func) | |
return func | |
end | |
}) | |
_AutoPassVargGen = setmetatable({}, { | |
__index = function(self, count) | |
local func = Toolset.loadsnippet(_PassVargsTemplate{ count = count }, "Case_VargsPass_" .. count, _ENV)() | |
rawset(self, count, func) | |
return func | |
end | |
}) | |
function __init(self) | |
local len = #self.vars | |
local min | |
local max = len | |
local immutable = true | |
local isvaragrs = false | |
for i = 1, len do | |
local var = self.vars[i] | |
if var.optional then | |
min = min or i - 1 | |
end | |
if var.varargs then | |
isvargs = true | |
max = 255 | |
if not var.mincount or var.mincount == 0 then | |
min = min or i - 1 | |
else | |
min = i + var.mincount - 1 | |
end | |
end | |
if not var.immutable then immutable = false end | |
end | |
self.min = min or len | |
self.max = max | |
self.validate = (isvaragrs and _AutoValidVargGen or _AutoValidGen)[len](unpack(self.vars)) | |
if immutable then | |
self.process= self.func | |
else | |
local pass = (isvaragrs and _AutoPassVargGen or _AutoPassGen)[len](unpack(self.vars)) | |
local func = self.func | |
self.process= function(...) return func(pass(...)) end | |
end | |
end | |
end) | |
__Sealed__() | |
class "Switch" (function(_ENV) | |
__Arguments__{ Case * 1 } | |
function __new(cls, ...) | |
return { ... }, true | |
end | |
function __ctor(self) | |
local count = #self | |
end | |
function __call(self, ...) | |
local count = select("#", ...) | |
for i = 1, #self do | |
local case = self[i] | |
if case.min <= count and count <= case.max then | |
if case.validate(...) then | |
return case.process(...) | |
end | |
end | |
end | |
end | |
end) | |
switcher = Switch( | |
Case ( | |
{ Number/0 }, | |
function (num) print("Age", num) end | |
), | |
Case ( | |
{ String }, | |
"x => print('Name', x)" | |
) | |
) | |
switcher(3) | |
switcher("Ann") | |
switcher() | |
end) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment