1 require 'compiler/system_hints'
4 # Turns text into CompiledMethods
11 # Compiler error subclass.
13 class Error < RuntimeError
16 def self.compile_file(path, flags=nil)
17 flags.each { |f| Config[f] = true } if flags
18 sexp = File.to_sexp(path, true)
21 node = comp.into_script(sexp)
22 return node.to_description(:__script__).to_cmethod
25 def self.compile_string(string, context=nil, filename="(eval)", line=1)
26 sexp = string.to_sexp(filename, line, true)
29 comp = new(Generator, context)
30 node = comp.convert_sexp([:eval_expression, sexp])
33 node = comp.into_script(sexp)
36 cm = node.to_description(:__eval_script__).to_cmethod
37 cm.file = filename.to_sym if filename and !filename.empty?
41 TimeEpoch = 1141027200 # rubinius' birthday
45 def self.version_number
46 unless @version_number
48 # handled for .rba files in init.rb
49 dir = $LOAD_PATH.detect { |path| File.file? "#{path}/compiler/compiler.rb" }
50 max = Dir["#{dir}/compiler/*.rb"].map { |f| File.mtime(f).to_i }.max
51 @version_number = max - TimeEpoch
57 STDERR.puts "[Compiler version: #{@version_number}]"
60 return @version_number
63 def self.version_number=(ver)
65 @version_number = ver - TimeEpoch
71 STDERR.puts "[Compiler version: #{@version_number} (forced)]"
75 def initialize(gen_class, context=nil)
77 @generator_class = gen_class
78 @plugins = Hash.new { |h,k| h[k]= [] }
84 @kernel = Config['rbx-kernel']
98 if ctx.kind_of? BlockContext
102 while ctx.kind_of? BlockContext
103 scope = LocalScope.new(nil)
104 scope.from_eval = true
105 block_scopes.unshift scope
108 if !ctx.env.from_eval? and names = ctx.method.local_names
111 scope[name].created_in_block! i
116 ctx = ctx.env.home_block
119 scope = LocalScope.new(nil)
120 scope.from_eval = true
123 if names = ctx.method.local_names
131 return [scope, block_scopes, all_scopes, @context]
133 scope = LocalScope.new(nil)
134 scope.from_eval = true
136 if names = ctx.method.local_names
143 return [scope, [], [scope], @context]
148 attr_accessor :generator_class
150 def set_position(file, line)
151 @file, @line = file, line
163 # The default plugins
164 activate_default :block_given
165 activate_default :primitive
166 activate_default :assembly
167 activate_default :fastmath
168 activate_default :current_method
169 activate :safemath if Config['rbx-safe-math']
170 activate :const_epxr if Config['rbx-kernel']
171 activate_default :inline if Config['rbx-inline-times']
172 activate_default :fastsystem
173 activate_default :fastgeneric
174 activate_default :auto_primitive
175 activate_default :conditional_compilation
178 def activate_default(name)
179 activate(name) unless Config["no-#{name}"]
183 cls = Plugins.find_plugin(name)
184 raise Error, "Unknown plugin '#{name}'" unless cls
185 @plugins[cls.kind] << cls.new(self)
192 def convert_sexp(sexp)
193 return nil if sexp.nil?
195 klass = Node::Mapping[sexp.first]
197 raise Error, "Unable to resolve #{sexp.first}" unless klass
199 return klass.create(self, sexp)
202 def into_script(sexp)
204 convert_sexp([:script, sexp])
206 puts "Compilation error detected: #{e.message}"
207 puts " near #{@file}:#{@line}"
209 puts e.awesome_backtrace.show
217 def set(tag, val=true)
220 @variables.merge! tag
227 cur = @variables[tag]
228 @variables[tag] = val
232 @variables[tag] = cur
238 # Raised when turning the AST into bytecode fails in some way.
240 class GenerationError < Error; end
245 rescue GenerationError => e
248 puts "Bytecode generation error: "
249 puts " #{e.message} (#{e.class})"
250 puts " near #{gen.file}:#{gen.line}"
252 puts e.awesome_backtrace.show
254 raise GenerationError, "unable to generate bytecode"
260 require 'compiler/nodes'
261 require 'compiler/local'
262 require 'compiler/bytecode'
263 require 'compiler/generator'
264 require 'compiler/plugins'