Class: Mirah::Generator

Inherits:
Object
  • Object
show all
Includes:
Logging::Logged, Util::ProcessErrors
Defined in:
lib/mirah/generator.rb

Constant Summary

Constants included from Logging::Logged

Logging::Logged::VLEVELS

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Logging::Logged

#error, #info, #log, #logger, #logger_name, #logging?, #vlog, #warning

Methods included from Util::ProcessErrors

#process_errors, #process_inference_errors

Constructor Details

#initialize(state, compiler_class, logging, verbose) ⇒ Generator

Returns a new instance of Generator.



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/mirah/generator.rb', line 26

def initialize(state, compiler_class, logging, verbose)
  @state = state

  # TODO untie this from the jvm backend (nh)
  if state.type_system
    # Using new type system
    @scoper = SimpleScoper.new do |scoper, node|
      scope = Java::OrgMirahJvmMirrors::JVMScope.new(scoper)
      scope.context_set(node)
      scope
    end
    type_system = state.type_system
  else
    @scoper = SimpleScoper.new {|scoper, node| Mirah::AST::StaticScope.new(node, scoper)}
    type_system = Mirah::JVM::Types::TypeFactory.new
    type_system.classpath = state.classpath if state.classpath
    type_system.bootclasspath = state.bootclasspath
  end

  @typer = Mirah::Typer::Typer.new(type_system, @scoper, self, nil)
  @parser = Mirah::Parser.new(state, @typer, logging)
  @compiler = Mirah::Compiler::ASTCompiler.new(state, compiler_class, logging)
  @extension_compiler = Mirah::Compiler::ASTCompiler.new(state, compiler_class, logging)
  if type_system.respond_to?(:maybe_initialize_builtins)
    type_system.maybe_initialize_builtins(@typer.macro_compiler)
  end
  @logging = logging
  @verbose = verbose
end

Instance Attribute Details

#compilerObject

Returns the value of attribute compiler.



56
57
58
# File 'lib/mirah/generator.rb', line 56

def compiler
  @compiler
end

#loggingObject

Returns the value of attribute logging.



56
57
58
# File 'lib/mirah/generator.rb', line 56

def logging
  @logging
end

#parserObject

Returns the value of attribute parser.



56
57
58
# File 'lib/mirah/generator.rb', line 56

def parser
  @parser
end

#typerObject

Returns the value of attribute typer.



56
57
58
# File 'lib/mirah/generator.rb', line 56

def typer
  @typer
end

#verboseObject

Returns the value of attribute verbose.



56
57
58
# File 'lib/mirah/generator.rb', line 56

def verbose
  @verbose
end

Instance Method Details

#compileAndLoadExtension(ast) ⇒ Object



126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/mirah/generator.rb', line 126

def compileAndLoadExtension(ast)
  log_types([ast])
  process_inference_errors(@typer, [ast])
  results = @extension_compiler.compile_asts([ast], @scoper, @typer)
  class_map = {}
  first_class_name = nil
  results.each do |result|
    classname = result.classname.gsub(/\//, '.')
    first_class_name ||= classname if classname.include?('$Extension')
    class_map[classname] = Mirah::Util::ClassLoader.binary_string result.bytes
    if @state.save_extensions
      filename = "#{@state.destination}#{result.filename}"
      FileUtils.mkdir_p(File.dirname(filename))
      File.open(filename, 'wb') {|f| f.write(result.bytes)}
    end
  end
  dcl = Mirah::Util::ClassLoader.new(JRuby.runtime.jruby_class_loader, class_map)
  dcl.load_class(first_class_name)
end

#do_transforms(nodes) ⇒ Object



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/mirah/generator.rb', line 74

def do_transforms nodes
  log("Starting Transform")

  java_import 'org.mirah.jvm.compiler.ClosureTransformer' rescue puts $!
  java_import 'org.mirah.util.Context' rescue puts $!
  #java_import 'org.mirah.typer.Typer'
  #java_import 'org.mirah.macros.Compiler'
  transformer = ClosureTransformer.new(Context.new.tap{|c|c.add(Java::org.mirah.typer::Typer, @typer) }) rescue nil
  if transformer
    nodes.each{|n| n.accept transformer, nil } # rescue log("transformer exception", $!.cause)
    log("POST Transform")
    log_types nodes
  else
    log "No transformer, skipping"
  end
end

#generate(arguments) ⇒ Object



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/mirah/generator.rb', line 58

def generate(arguments)
  # collect all ASTs from all files
  top_nodes = parser.parse_from_args(arguments)

  # enter all ASTs into inference engine
  puts "Inferring types..." if logging
  scoper, typer = infer_asts(top_nodes)
  do_transforms top_nodes
  # compile each AST in turn
  compiler_results = compiler.compile_asts(top_nodes, scoper, typer)

  puts "Done!" if logging

  compiler_results
end

#infer_asts(nodes, should_raise = false) ⇒ Object



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/mirah/generator.rb', line 91

def infer_asts(nodes, should_raise=false)
  log_and_reraise "Caught exception during type inference" do
    nodes.each {|ast| @typer.infer(ast, false) }
    if should_raise
      error_handler = lambda do |errors|
        message, position = errors[0].message[0].to_a
        raise Mirah::MirahError.new(message, position)
      end
    end
    process_inference_errors(@typer, nodes, &error_handler)
  end
  [@scoper, @typer]
ensure
  log_types(nodes)
end

#log_and_reraise(message) ⇒ Object



107
108
109
110
111
112
# File 'lib/mirah/generator.rb', line 107

def log_and_reraise message
  yield
rescue NativeException => ex
  log(message, ex.cause)
  raise ex
end

#log_types(nodes) ⇒ Object



114
115
116
117
118
119
120
121
122
123
124
# File 'lib/mirah/generator.rb', line 114

def log_types(nodes)
  if self.logging?
    buf = java.io.ByteArrayOutputStream.new
    ps = java.io.PrintStream.new(buf)
    printer = TypePrinter.new(@typer, ps)
    nodes.each {|ast| printer.scan(ast, nil)}
    ps.close()
    log("Inferred types:\n{0}", java.lang.String.new(buf.toByteArray))
  end

end

#logExtensionAst(ast) ⇒ Object



146
147
148
# File 'lib/mirah/generator.rb', line 146

def logExtensionAst(ast)
  log("Extension ast:\n#{parser.format_ast(ast)}")
end