Created
November 8, 2011 18:47
-
-
Save reusee/1348701 to your computer and use it in GitHub Desktop.
lua object emulator
This file contains 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
local yield = coroutine.yield | |
local create = coroutine.create | |
local status = coroutine.status | |
local resume = coroutine.resume | |
local setmetatable = setmetatable | |
local next = next | |
local pop = table.remove | |
local insert = table.insert | |
local type = type | |
local pairs = pairs | |
World_meta = { | |
__index = { | |
run = function(self) | |
while self:tick() do | |
end | |
end, | |
tick = function(self) | |
if self.stop then | |
do return false end | |
end | |
self:dispatch_signals() | |
self:do_tasks() | |
return true | |
end, | |
dispatch_signals = function(self) | |
while next(self.signals) ~= nil do | |
local signal = pop(self.signals) | |
local source = signal[1] | |
local target = signal[2] | |
local signal_type = signal[3] | |
local signal_data = signal[4] | |
if type(target) == 'string' then | |
target = self.named_objects[target] | |
end | |
insert(target.tasks, {'signal', source, signal_type, signal_data}) | |
end | |
end, | |
do_tasks = function(self) | |
for _, obj in pairs(self.objects) do | |
if next(obj.tasks) ~= nil then | |
local task = pop(obj.tasks) | |
if type(task) == 'table' then | |
if task[1] == 'signal' then | |
local source = task[2] | |
local signal_type = task[3] | |
local signal_data = task[4] | |
for _, handler in pairs(obj.handlers[signal_type]) do | |
local c = create(handler) | |
resume(c, obj, source, signal_type, signal_data) | |
if status(c) ~= 'dead' then | |
insert(obj.tasks, c) | |
end | |
end | |
end | |
elseif type(task) == 'thread' then | |
resume(task) | |
if status(task) ~= 'dead' then | |
insert(obj.tasks, task) | |
end | |
end | |
end | |
end | |
end, | |
} | |
} | |
function World() | |
local world = {} | |
world.signals = {} | |
world.objects = {} | |
world.named_objects = { | |
world = world, | |
} | |
world.start_time = nil | |
world.count = nil | |
world.show_tps = false | |
world.stop = false | |
world.commands = { | |
stop = function() | |
world.stop = true | |
end, | |
} | |
setmetatable(world, World_meta) | |
return world | |
end | |
Thing_meta = { | |
__index = { | |
connect = function(self, signal_type, handler) | |
if self.handlers[signal_type] == nil then | |
self.handlers[signal_type] = {} | |
end | |
insert(self.handlers[signal_type], handler) | |
end, | |
send = function(self, target, signal_type, signal_data) | |
if target == 'world' then | |
self.world.commands[signal_type](signal_data) | |
else | |
insert(self.world.signals, {self, target, signal_type, signal_data}) | |
end | |
end, | |
}, | |
} | |
function Thing(world) | |
local obj = {} | |
obj.world = world | |
obj.tasks = {} | |
obj.handlers = {} | |
insert(world.objects, obj) | |
setmetatable(obj, Thing_meta) | |
return obj | |
end | |
world = World() | |
ping = Thing(world) | |
pong = Thing(world) | |
pong:connect('ping', function(self, source, signal, ttl) | |
if ttl < 1 then | |
self:send('world', 'stop') | |
end | |
--print('going to pong') | |
yield() | |
--print('really going to pong') | |
yield() | |
--print('i swear i am not a procrastinator') | |
yield() | |
--print('pong') | |
self:send(source, 'pong', ttl - 1) | |
end) | |
--pong:connect('ping', function(self, source, signal, ttl) | |
-- print('ah, someone pong me') | |
--end) | |
ping:connect('pong', function(self, source, signal, ttl) | |
if ttl < 1 then | |
self:send('world', 'stop') | |
end | |
--print('ping') | |
self:send(source, 'ping', ttl - 1) | |
end) | |
ping:send(pong, 'ping', 420000) | |
world:run() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment