Skip to content

Commit

Permalink
Use threads for parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
Ryan Brown committed Nov 3, 2010
1 parent bfcbca0 commit eb5f8c0
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 50 deletions.
10 changes: 9 additions & 1 deletion bin/mirahp
Expand Up @@ -6,4 +6,12 @@ rescue LoadError
require 'mirah'
end

puts Duby.parse(*ARGV).inspect
asts = Duby.parse(*ARGV)
if asts.size == 1
puts asts[0].inspect
else
asts.each do |ast|
next if Duby::AST::ErrorNode === ast
puts "#{ast.filename}:", ast.inspect, ""
end
end
113 changes: 65 additions & 48 deletions lib/mirah.rb
Expand Up @@ -2,6 +2,7 @@
require 'rbconfig'
require 'mirah/transform'
require 'mirah/ast'
require 'mirah/threads'
require 'mirah/typer'
require 'mirah/compiler'
require 'mirah/env'
Expand Down Expand Up @@ -71,7 +72,23 @@ def self.print_error(message, position)
end

class CompilationState
attr_accessor :verbose, :destination
attr_accessor :verbose, :destination, :builtins_initialized
attr_reader :executor, :mutex, :main_thread

def initialize
@executor = Duby::Threads::Executor.new
@mutex = Mutex.new
@main_thread = Thread.current
end

def log(message)
# TODO allow filtering which logs to show.
if verbose
@mutex.synchronize {
puts message
}
end
end
end
end

Expand All @@ -83,7 +100,7 @@ def initialize(parent, class_map)
super(parent)
@class_map = class_map
end

def findClass(name)
if @class_map[name]
bytes = @class_map[name].to_java_bytes
Expand Down Expand Up @@ -156,22 +173,7 @@ def compile(*args)
end

def generate(args, &block)
process_flags!(args)

# collect all ASTs from all files
all_nodes = []
expand_files(args).each do |duby_file|
if duby_file == '-e'
@filename = '-e'
next
elsif @filename == '-e'
all_nodes << parse('-e', duby_file)
else
all_nodes << parse(duby_file)
end
@filename = nil
exit 1 if @error
end
all_nodes = parse(*args)

# enter all ASTs into inference engine
infer_asts(all_nodes)
Expand All @@ -184,36 +186,42 @@ def generate(args, &block)

def parse(*args)
process_flags!(args)
@filename = args.shift

if @filename
if @filename == '-e'
@filename = 'DashE'
src = args[0]
else
src = File.read(@filename)
end
else
files = expand_files(args)
if files.empty?
print_help
exit(1)
end
begin
ast = Duby::AST.parse_ruby(src, @filename)
# rescue org.jrubyparser.lexer.SyntaxException => ex
# Duby.print_error(ex.message, ex.position)
# raise ex if @state.verbose
end
@transformer = Duby::Transform::Transformer.new(@state)
Java::MirahImpl::Builtin.initialize_builtins(@transformer)
@transformer.filename = @filename
ast = @transformer.transform(ast, nil)
@transformer.errors.each do |ex|
Duby.print_error(ex.message, ex.position)
raise ex.cause || ex if @state.verbose

# collect all ASTs from all files
all_nodes = @state.executor.each(files) do |pair|
filename, src = pair
begin
ast = Duby::AST.parse_ruby(src, filename)
# rescue org.jrubyparser.lexer.SyntaxException => ex
# Duby.print_error(ex.message, ex.position)
# raise ex if @state.verbose
end
transformer = Duby::Transform::Transformer.new(@state)
@state.mutex.synchronize {
@state.builtins_initialized ||= begin
Java::MirahImpl::Builtin.initialize_builtins(transformer)
true
end
}
transformer.filename = filename
ast = transformer.transform(ast, nil)
@state.mutex.synchronize {
transformer.errors.each do |ex|
Duby.print_error(ex.message, ex.position)
raise ex.cause || ex if @state.verbose
end
}
@error ||= transformer.errors.size > 0
ast
end
@error = @transformer.errors.size > 0

ast
all_nodes
end

def infer_asts(asts)
Expand Down Expand Up @@ -247,9 +255,11 @@ def compile_ast(ast, &block)
compiler.generate(&block)
rescue Exception => ex
if ex.respond_to? :node
Duby.print_error(ex.message, ex.node.position)
puts ex.backtrace if @state.verbose
exit 1
@state.mutex.synchronize {
Duby.print_error(ex.message, ex.node.position)
@state.log(ex.backtrace)
}
@error = true
else
raise ex
end
Expand Down Expand Up @@ -319,17 +329,24 @@ def print_help

def expand_files(files)
expanded = []
dash_e = false
files.each do |filename|
if File.directory?(filename)
if dash_e
expanded << ['DashE', filename]
dash_e = false
elsif filename == '-e'
dash_e = true
next
elsif File.directory?(filename)
Dir[File.join(filename, '*')].each do |child|
if File.directory?(child)
files << child
elsif child =~ /\.(duby|mirah)$/
expanded << child
expanded << [child, File.read(child)]
end
end
else
expanded << filename
expanded << [filename, File.read(filename)]
end
end
expanded
Expand Down
2 changes: 1 addition & 1 deletion lib/mirah/ast/intrinsics.rb
Expand Up @@ -252,7 +252,7 @@ def build_and_load_extension(parent, name, state)
new_factory = orig_factory.dup
Duby::AST.type_factory = new_factory
ast = build_ast(name, parent, transformer)
puts ast.inspect if state.verbose
state.log(ast.inspect)
classes = compile_ast(name, ast, transformer)
loader = DubyClassLoader.new(
JRuby.runtime.jruby_class_loader, classes)
Expand Down
52 changes: 52 additions & 0 deletions lib/mirah/threads.rb
@@ -1,4 +1,5 @@
require 'jruby/synchronized'
require 'thread'

module Duby
module Threads
Expand All @@ -9,5 +10,56 @@ class SynchronizedArray < Array
class SynchronizedHash < Hash
include JRuby::Synchronized
end

class Executor
java_import 'java.util.concurrent.Executors'

def initialize(executor=nil)
@executor = executor ||
Executors.new_cached_thread_pool(DaemonThreadFactory.new)
end

class DaemonThreadFactory
java_import 'java.util.concurrent.ThreadFactory'
java_import 'java.lang.Thread'
include ThreadFactory

def newThread(runnable)
thread = Thread.new(runnable)
thread.setDaemon(true)
thread
end
end

class MirahTask
java_import 'java.util.concurrent.Callable'
include Callable

def initialize(factory=nil, &block)
@factory = factory || Duby::AST.type_factory
@block = block
end

def call
Duby::AST.type_factory = @factory
@block.call
end
end

def each(list)
tasks = list.map do |x|
MirahTask.new do
yield x
end
end
futures = @executor.invoke_all(tasks)
futures.map {|x| x.get}
end

def execute(&block)
each([nil], &block)[0]
end
end

end
end

0 comments on commit eb5f8c0

Please sign in to comment.