Skip to content

Instantly share code, notes, and snippets.

@Freezerburn
Created September 22, 2019 18:00
Show Gist options
  • Save Freezerburn/57211f7e4dd65d42d0e1214eb590d9a7 to your computer and use it in GitHub Desktop.
Save Freezerburn/57211f7e4dd65d42d0e1214eb590d9a7 to your computer and use it in GitHub Desktop.
class Module
def stateful(*args)
state_name = self.name
state_var_name = "@#{state_name}".to_sym
args_var_sym = "@args".to_sym
tmp_var_arr_name = "@_#{state_name}_tmp_vars".to_sym
set_tmp_var = ->(to, key, name, value) {
tmp_var_arr = to.instance_variable_get(tmp_var_arr_name)
if tmp_var_arr.nil?
tmp_var_arr = []
to.instance_variable_set(tmp_var_arr_name, tmp_var_arr)
end
to.instance_variable_set(name, value)
tmp_key = tmp_var_arr.find { |v| v[0] == key }
if tmp_key.nil?
tmp_var_arr << [ key, name ]
end
value
}
if !respond_to?(:args=)
define_method 'args=' do |value|
current_args = self.args
if current_args.nil?
my_state = value.state.new_entity(state_name.to_sym)
instance_variable_set(state_var_name, my_state)
tmp_var_arr = instance_variable_get(tmp_var_arr_name)
if !tmp_var_arr.nil?
tmp_var_arr.each do |key, property|
tmp_value = instance_variable_get(property)
my_state.send("#{key}=".to_sym, tmp_value)
end
instance_variable_set(tmp_var_arr_name, nil)
end
end
instance_variable_set(args_var_sym, value)
end
define_method 'args' do
instance_variable_get(args_var_sym)
end
define_method 'state' do
instance_variable_get(state_var_name)
end
end
args.each do |key|
getter_name = key.to_s
setter_name = "#{getter_name}="
state_setter = setter_name.to_sym
tmp_var_name = "@_tmp_#{getter_name}".to_sym
define_method getter_name do
state_var = self.state
if state_var.nil?
ret = instance_variable_get(tmp_var_name)
else
ret = state_var.send(key)
end
end
define_method setter_name do |value|
state_var = self.state
if state_var.nil?
set_tmp_var.call(self, key, tmp_var_name, value)
else
state_var.send(state_setter, value)
end
end
end
end
end
class Foo
stateful :x, :y
def initialize(x, y)
self.x = x
self.y = y
end
def tick(args)
self.args = args
args.outputs.labels << [ self.x, self.y, 'A test with stateful' ]
end
end
$foo = Foo.new(100, 100)
def tick(args)
$foo.tick(args)
$foo.x += 1
$foo.y += 1
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment