Skip to content

Instantly share code, notes, and snippets.

@pachacamac
Last active August 29, 2015 14:26
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pachacamac/b9dcb1242071902b92db to your computer and use it in GitHub Desktop.
Save pachacamac/b9dcb1242071902b92db to your computer and use it in GitHub Desktop.
Flow Based Programming test
class FBPNode
attr_accessor :inputs, :outputs, :opts, :processor, :input_buffers
def initialize(opts={}, &block)
@inputs = opts[:inputs] || []
@outputs = opts[:outputs] || []
@options = opts[:options] || {}
@name = opts[:name]
@debug = true
@processor = block
@input_buffers = @inputs.reduce({}){|s,e| s[e] = []; s}
@output_connectors = @outputs.reduce({}){|s,e| s[e] = []; s}
end
def input(key, value)
puts "#{value} -> #{self}[#{key}] - #{@input_buffers} - #{@input_buffers.values.map(&:size).min}" if @debug
@input_buffers[key] << value
puts "#{self} got #{@input_buffers.values.map(&:size).min} usable buffer entries" if @debug
@input_buffers.values.map(&:size).min.times do
params = @input_buffers.reduce({}){|s,(k,v)| s[k] = v.shift; s }
transmit(@processor.call(*params.values, @options))
end
end
def emit
transmit(@processor.call(@options))
end
def connect(output, node, input)
@output_connectors[output] << [node, input]
end
def transmit(result)
@output_connectors.each do |output, connectors|
connectors.each do |node, input|
puts "#{self}[#{output}] -> #{node}[#{input}]" if @debug
node.input(input, result[@outputs.find_index(output)])
end
end
end
def inspect; to_s; end
def to_s; @name ? @name : super; end
end
random = proc{|opts| [rand(opts[:range]||(0..99))]}
modulo = proc{|numerator, denominator, opts| [(numerator/denominator).to_i, numerator%denominator]}
adder = proc{|a, b, opts| [a + b]}
number = proc{|opts| [opts[:number]||0]}
printer = proc{|text, opts| puts text; [text]}
prepender = proc{|inp, opts| ["#{opts[:text]}#{inp}"]}
random_number_emitter = FBPNode.new(name: 'random_number_emitter',
outputs: [:random], options: {range: 0..9}, &random)
random_number_emitter2 = FBPNode.new(name: 'random_number_emitter2',
outputs: [:random], options: {range: 0..99}, &random)
mod = FBPNode.new(name: 'modulo',
inputs: [:numerator, :denominator], outputs: [:quotient, :remainder], &modulo)
plus = FBPNode.new(name: 'plus',
inputs: [:a, :b], outputs: [:result], &adder)
number_3_emitter = FBPNode.new(name: 'number_3_emitter',
outputs: [:out], options: {number: 3}, &number)
print = FBPNode.new(name: 'print', inputs: [:data], outputs: [:data], &printer)
prependerQ = FBPNode.new(name: 'prependerQ',
inputs: [:inp], outputs: [:out], options: {text: 'Q'}, &prepender)
prependerR = FBPNode.new(name: 'prependerR',
inputs: [:inp], outputs: [:out], options: {text: 'R'}, &prepender)
random_number_emitter.connect(:random, plus, :b)
random_number_emitter.connect(:random, mod, :denominator)
random_number_emitter2.connect(:random, plus, :a)
plus.connect(:result, mod, :numerator)
mod.connect(:quotient, prependerQ, :inp)
mod.connect(:remainder, prependerR, :inp)
prependerQ.connect(:out, print, :data)
prependerR.connect(:out, print, :data)
random_number_emitter.emit
random_number_emitter2.emit
#
# random_number_emitter2 --> plus prependerQ --> print
# / \ /
# random_number_emitter --* (N) (Q)
# \ \ /
# \___(D)_ mod --> prependerR --> print
#
# example output with debug option
#
# random_number_emitter[random] -> plus[b]
# 6 -> plus[b] - {:a=>[], :b=>[]} - 0
# plus got 0 usable buffer entries
# random_number_emitter[random] -> modulo[denominator]
# 6 -> modulo[denominator] - {:numerator=>[], :denominator=>[]} - 0
# modulo got 0 usable buffer entries
# random_number_emitter2[random] -> plus[a]
# 38 -> plus[a] - {:a=>[], :b=>[6]} - 0
# plus got 1 usable buffer entries
# plus[result] -> modulo[numerator]
# 44 -> modulo[numerator] - {:numerator=>[], :denominator=>[6]} - 0
# modulo got 1 usable buffer entries
# modulo[quotient] -> prependerQ[inp]
# 7 -> prependerQ[inp] - {:inp=>[]} - 0
# prependerQ got 1 usable buffer entries
# prependerQ[out] -> print[data]
# Q7 -> print[data] - {:data=>[]} - 0
# print got 1 usable buffer entries
# Q7
# modulo[remainder] -> prependerR[inp]
# 2 -> prependerR[inp] - {:inp=>[]} - 0
# prependerR got 1 usable buffer entries
# prependerR[out] -> print[data]
# R2 -> print[data] - {:data=>[]} - 0
# print got 1 usable buffer entries
# R2
#
# -> Q7, R2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment