require 'mirah' module Duby class PathArray < Array def <<(value) super(File.expand_path(value)) end end def self.source_path source_paths[0] ||= File.expand_path('.') end def self.source_paths @source_paths ||= PathArray.new end def self.source_path=(path) source_paths[0] = File.expand_path(path) end def self.dest_paths @dest_paths ||= PathArray.new end def self.dest_path dest_paths[0] ||= File.expand_path('.') end def self.dest_path=(path) dest_paths[0] = File.expand_path(path) end def self.find_dest(path) expanded = File.expand_path(path) dest_paths.each do |destdir| if expanded =~ /^#{destdir}\// return destdir end end end def self.find_source(path) expanded = File.expand_path(path) source_paths.each do |sourcedir| if expanded =~ /^#{sourcedir}\// return sourcedir end end end def self.dest_to_source_path(target_path) destdir = find_dest(target_path) path = File.expand_path(target_path).sub(/^#{destdir}\//, '') path.sub!(/\.(java|class)$/, '') snake_case = File.basename(path).gsub(/[A-Z]/, '_\0').sub(/_/, '').downcase snake_case = "#{File.dirname(path)}/#{snake_case}" source_paths.each do |source_path| ["mirah", "duby"].each do |suffix| filename = "#{source_path}/#{path}.#{suffix}" return filename if File.exist?(filename) filename = "#{source_path}/#{snake_case}.#{suffix}" return filename if File.exist?(filename) end end # No source file exists. Just go with the first source path and .mirah return "#{self.source_path}/#{path}.mirah" end def self.compiler_options @compiler_options ||= [] end def self.compiler_options=(args) @compiler_options = args end end def mirahc(*files) if files[-1].kind_of?(Hash) options = files.pop else options = {} end source_dir = options.fetch(:dir, Duby.source_path) dest = File.expand_path(options.fetch(:dest, Duby.dest_path)) files = files.map {|f| f.sub(/^#{source_dir}\//, '')} flags = options.fetch(:options, Duby.compiler_options) args = ['-d', dest, *flags] + files chdir(source_dir) do puts "mirahc #{args.join ' '}" Duby.compile(*args) Duby.reset end end rule '.java' => [proc {|n| Duby.dest_to_source_path(n)}] do |t| mirahc(t.source, :dir=>Duby.find_source(t.source), :dest=>Duby.find_dest(t.name), :options=>['-java']) end rule '.class' => [proc {|n| Duby.dest_to_source_path(n)}] do |t| mirahc(t.source, :dir=>Duby.find_source(t.source), :dest=>Duby.find_dest(t.name)) end