LoginSignup
7
7

More than 5 years have passed since last update.

FLOWer interpreter on Ruby

Last updated at Posted at 2014-03-20

Usage: flower.rb [<] flower.json
※flower.jsonはダウンロードしたzipを展開すると取り出せます。

本家FLOWerのジョブの3割ほどをカバーしています。
挙動については私の類推です。
条件分岐はドキュメントがないため実装できませんでした。。

複数のジョブから一度に値を受け取った時は先に生成されたジョブから受け取った値を先に使用するという挙動は再現出来ているはずです。

flower.rb
#!/usr/bin/ruby
require 'json'

#FLOWer Job parent
class FLOWerJob
    def initialize(jobs,inputports,constant,outputports)
        @jobs=jobs # fixme
        @queue=Hash.new{|h,k|h[k]=[]}
        @inputports=inputports
        @constant=constant
        @outputports=outputports
        @input={}
        @constant.each{|k,v|
            @input[k]=v
        }
    end
    def send_value(port,value)
        @queue[port]<< value
    end
    def accept_value
        @queue.each{|k,v|
            if @input[k]==nil && v.size>0
                @input[k]=v.shift
            end
        }
    end
    def query
        return if @inputports.any?{|e|@input[e]==nil}
        query2
        @inputports.each{|e|
            @input[e]=nil if !@constant.has_key?(e)
        }
    end
end

#FLOWer Jobs
#core
class FLOWerJob_core_Through <FLOWerJob
    def query2
        value=@input['input']
        @outputports['output'].each{|job,port|
            @jobs[job].send_value(port,value)
        }
    end
end
class FLOWerJob_core_Add <FLOWerJob
    def query2
        value=@input['input1']+@input['input2']
        @outputports['output'].each{|job,port|
            @jobs[job].send_value(port,value)
        }
    end
end
class FLOWerJob_core_Times <FLOWerJob
    def query2
        value=@input['input1']*@input['input2']
        @outputports['output'].each{|job,port|
            @jobs[job].send_value(port,value)
        }
    end
end
class FLOWerJob_core_And <FLOWerJob
    def query2
        value=@input['input1']&@input['input2']
        @outputports['output'].each{|job,port|
            @jobs[job].send_value(port,value)
        }
    end
end
class FLOWerJob_core_Or <FLOWerJob
    def query2
        value=@input['input1']|@input['input2']
        @outputports['output'].each{|job,port|
            @jobs[job].send_value(port,value)
        }
    end
end
class FLOWerJob_core_Transistor <FLOWerJob
    def query2
        value=@input['emitter']
        @outputports['collector'].each{|job,port|
            @jobs[job].send_value(port,value)
        }
    end
end
#number
class FLOWerJob_number_C0 <FLOWerJob
    def query2
        value=0
        @outputports['0'].each{|job,port|
            @jobs[job].send_value(port,value)
        }
    end
end
class FLOWerJob_number_C1 <FLOWerJob
    def query2
        value=1
        @outputports['1'].each{|job,port|
            @jobs[job].send_value(port,value)
        }
    end
end
class FLOWerJob_number_C2 <FLOWerJob
    def query2
        value=2
        @outputports['2'].each{|job,port|
            @jobs[job].send_value(port,value)
        }
    end
end
class FLOWerJob_number_C3 <FLOWerJob
    def query2
        value=3
        @outputports['3'].each{|job,port|
            @jobs[job].send_value(port,value)
        }
    end
end
class FLOWerJob_number_C4 <FLOWerJob
    def query2
        value=4
        @outputports['4'].each{|job,port|
            @jobs[job].send_value(port,value)
        }
    end
end
class FLOWerJob_number_C5 <FLOWerJob
    def query2
        value=5
        @outputports['5'].each{|job,port|
            @jobs[job].send_value(port,value)
        }
    end
end
class FLOWerJob_number_C6 <FLOWerJob
    def query2
        value=6
        @outputports['6'].each{|job,port|
            @jobs[job].send_value(port,value)
        }
    end
end
class FLOWerJob_number_C7 <FLOWerJob
    def query2
        value=7
        @outputports['7'].each{|job,port|
            @jobs[job].send_value(port,value)
        }
    end
end
class FLOWerJob_number_C8 <FLOWerJob
    def query2
        value=8
        @outputports['8'].each{|job,port|
            @jobs[job].send_value(port,value)
        }
    end
end
class FLOWerJob_number_C9 <FLOWerJob
    def query2
        value=9
        @outputports['9'].each{|job,port|
            @jobs[job].send_value(port,value)
        }
    end
end
#math
class FLOWerJob_math_Abs <FLOWerJob
    def query2
        value=@input['input'].abs
        @outputports['output'].each{|job,port|
            @jobs[job].send_value(port,value)
        }
    end
end
class FLOWerJob_math_Max <FLOWerJob
    def query2
        value=[@input['a'],@input['b']].max
        @outputports['output'].each{|job,port|
            @jobs[job].send_value(port,value)
        }
    end
end
class FLOWerJob_math_Max <FLOWerJob
    def query2
        value=[@input['a'],@input['b']].min
        @outputports['output'].each{|job,port|
            @jobs[job].send_value(port,value)
        }
    end
end
#system
class FLOWerJob_system_Speed <FLOWerJob
    def query2
        value=@input['speed']
        # do nothing here
        @outputports['output'].each{|job,port|
            @jobs[job].send_value(port,value)
        }
    end
end
class FLOWerJob_system_Print <FLOWerJob
    def query2
        value=@input['input']
        print value.to_s+', '
        @outputports['output'].each{|job,port|
            @jobs[job].send_value(port,value)
        }
    end
end
class FLOWerJob_system_Scan <FLOWerJob
    def query2
        #value=@input['input']
        print 'input> '
        value=gets.to_i
        @outputports['output'].each{|job,port|
            @jobs[job].send_value(port,value)
        }
    end
end
#snapsvg
#snapelement
#map
#string
#array

#flower.json runner
class FLOWer
    def initialize(json_str)
        json=JSON.parse(json_str)
        @jobs={}
        json['diagram']['jobs'].each{|e|
            id=e['id']
            constant={}
            inputports=[]
            e['inputports'].each{|f|
                inputports<<f['name']
                if f['constant']
                    constant[f['name']]=f['constant']['value']
                end
            }
            if e['ref']
                ref=e['ref']
            else
                ref='core.Through'
                inputports=['input']
                @entry=id
            end
            outputports={}
            e['outputports'].map{|f|
                outputports[f['name']]=f['connections'].map{|e|e.split('.')}
            }
            #If NameError is thrown here, that means the job is not implemented yet.
            @jobs[id]=Object.const_get('FLOWerJob_'+ref.gsub('.','_')).new(@jobs,inputports,constant,outputports)
        }
    end
    def run
        @jobs[@entry].send_value('input',0)
        @jobs[@entry].accept_value
        loop{
            @jobs.each{|k,v|
                v.query
            }
            @jobs.each{|k,v|
                v.accept_value
            }
        }
    end
end
FLOWer.new($<.read).run
7
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
7