Class: Mirah::AST::MacroDefinition
- Defined in:
- lib/mirah/ast/intrinsics.rb
Instance Attribute Summary collapse
-
#proxy ⇒ Object
Returns the value of attribute proxy.
Attributes included from Named
Attributes inherited from Node
#children, #inferred_type, #newline, #parent, #position
Class Method Summary collapse
Instance Method Summary collapse
- #annotate(type, class_name) ⇒ Object
- #argument_types ⇒ Object
- #build_and_load_extension(parent, name, state) ⇒ Object
- #build_ast(name, parent, transformer) ⇒ Object
- #compile_ast(name, ast, transformer) ⇒ Object
- #infer(typer, expression) ⇒ Object
-
#initialize(parent, line_number, name, &block) ⇒ MacroDefinition
constructor
A new instance of MacroDefinition.
- #signature ⇒ Object
Methods included from Scoped
Methods included from Named
#string_value, #to_s, #validate_name
Methods inherited from Node
#<<, ===, #[], #[]=, #_dump, _load, #_set_parent, child, child_name, #child_nodes, #each, #empty?, #expr?, #inferred_type!, #initialize_copy, #insert, #inspect, #inspect_children, #line_number, #log, #precompile, #resolve_if, #resolved!, #resolved?, #simple_name, #string_value, #temp, #to_s, #top_level?, #validate_child, #validate_children
Constructor Details
#initialize(parent, line_number, name, &block) ⇒ MacroDefinition
Returns a new instance of MacroDefinition.
266 267 268 269 |
# File 'lib/mirah/ast/intrinsics.rb', line 266 def initialize(parent, line_number, name, &block) super(parent, line_number, &block) self.name = name end |
Instance Attribute Details
#proxy ⇒ Object
Returns the value of attribute proxy.
259 260 261 |
# File 'lib/mirah/ast/intrinsics.rb', line 259 def proxy @proxy end |
Class Method Details
.new(*args, &block) ⇒ Object
261 262 263 264 |
# File 'lib/mirah/ast/intrinsics.rb', line 261 def self.new(*args, &block) real_node = super real_node.proxy = NodeProxy.new(real_node) end |
Instance Method Details
#annotate(type, class_name) ⇒ Object
332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 |
# File 'lib/mirah/ast/intrinsics.rb', line 332 def annotate(type, class_name) node = type..node if node extension = node.annotation('duby.anno.Extensions') extension ||= begin node.annotations << Annotation.new( nil, nil, BiteScript::ASM::Type.getObjectType('duby/anno/Extensions')) node.annotations[-1].runtime = false node.annotations[-1] end extension['macros'] ||= [] macro = Annotation.new(nil, nil, BiteScript::ASM::Type.getObjectType('duby/anno/Macro')) macro['name'] = name macro['signature'] = BiteScript::Signature.signature(*signature) macro['class'] = class_name extension['macros'] << macro # TODO deal with optional blocks. else puts "Warning: No ClassDefinition for #{type.name}. Macros can't be loaded from disk." end end |
#argument_types ⇒ Object
294 295 296 297 298 299 300 301 302 303 304 |
# File 'lib/mirah/ast/intrinsics.rb', line 294 def argument_types arguments.map do |arg| if arg.kind_of?(BlockArgument) TypeReference::BlockType else # TODO support typed args. Also there should be a way # to accept any AST node. Mirah::JVM::Types::Object end end end |
#build_and_load_extension(parent, name, state) ⇒ Object
314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 |
# File 'lib/mirah/ast/intrinsics.rb', line 314 def build_and_load_extension(parent, name, state) transformer = Mirah::Transform::Transformer.new(state) transformer.filename = name.gsub(".", "/") orig_factory = Mirah::AST.type_factory new_factory = orig_factory.dup Mirah::AST.type_factory = new_factory ast = build_ast(name, parent, transformer) classes = compile_ast(name, ast, transformer) loader = Mirah::Util::ClassLoader.new( JRuby.runtime.jruby_class_loader, classes) klass = loader.loadClass(name, true) if state.save_extensions annotate(parent, name) end Mirah::AST.type_factory = orig_factory klass end |
#build_ast(name, parent, transformer) ⇒ Object
386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 |
# File 'lib/mirah/ast/intrinsics.rb', line 386 def build_ast(name, parent, transformer) # TODO should use a new type factory too. ast = Mirah::AST.parse_ruby("begin;end") ast = transformer.transform(ast, nil) # Start building the extension class extension = transformer.define_class(position, name) #extension.superclass = Mirah::AST.type(nil, 'duby.lang.compiler.Macro') extension.implements(Mirah::AST.type(nil, 'duby.lang.compiler.Macro')) extension.static_scope.import('duby.lang.compiler.Node', 'Node') extension.static_scope.package = scope.static_scope.package # The constructor just saves the state extension.define_constructor( position, ['mirah', Mirah::AST.type(nil, 'duby.lang.compiler.Compiler')], ['call', Mirah::AST.type(nil, 'duby.lang.compiler.Call')]) do |c| transformer.eval("@mirah = mirah;@call = call", '-', c, 'mirah', 'call') end node_type = Mirah::AST.type(nil, 'duby.lang.compiler.Node') # expand() parses the arguments out of call and then passes them off to # _expand = extension.define_method( position, 'expand', node_type) pos = parent.position args = [] = FunctionalCall.new(nil, pos, '_expand') self.arguments.each_with_index do |arg, i| # TODO optional args args << if arg.kind_of?(BlockArgument) Call.new(, pos, 'block') do |block_call| [Field.new(block_call, pos, 'call'), [], nil] end else cast = FunctionalCall.new(, pos, 'duby.lang.compiler.Node') cast.cast = true cast.parameters = [] << Call.new(cast, pos, 'get') do |getcall| [Local.new(getcall, pos, 'args'), [Fixnum.new(getcall, pos, i)], nil] end cast end end .parameters = args .body = transformer.eval(<<-end) args = @call.arguments nil end .body << actual_args = arguments.map do |arg| type = if arg.kind_of?(BlockArgument) Mirah::AST.type(nil, 'duby.lang.compiler.Block') else node_type end [arg.name, type, arg.position] end m = extension.define_method(position, '_expand', node_type, *actual_args) scope.static_scope.imports.each do |short, long| m.static_scope.import(long, short) end scope.static_scope.search_packages.each do |package| m.static_scope.import(package, '*') end m.body = self.body ast.body = extension ast end |
#compile_ast(name, ast, transformer) ⇒ Object
355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 |
# File 'lib/mirah/ast/intrinsics.rb', line 355 def compile_ast(name, ast, transformer) begin # FIXME: This is JVM specific, and should move out of platform-independent code typer = Mirah::JVM::Typer.new(transformer) typer.infer(ast, false) typer.resolve(true) typer.errors.each do |e| raise e end ensure puts ast.inspect if transformer.state.verbose end # FIXME: This is JVM specific, and should move out of platform-independent code compiler = Mirah::JVM::Compiler::JVMBytecode.new ast.compile(compiler, false) class_map = {} compiler.generate do |outfile, builder| bytes = builder.generate name = builder.class_name.gsub(/\//, '.') class_map[name] = Mirah::Util::ClassLoader.binary_string bytes if transformer.state.save_extensions outfile = "#{transformer.destination}#{outfile}" FileUtils.mkdir_p(File.dirname(outfile)) File.open(outfile, 'wb') do |f| f.write(bytes) end end end class_map end |
#infer(typer, expression) ⇒ Object
271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 |
# File 'lib/mirah/ast/intrinsics.rb', line 271 def infer(typer, expression) resolve_if(typer) do self_type = scope.static_scope.self_type extension_name = "%s$%s" % [self_type.name, typer.transformer.tmp("Extension%s")] klass = build_and_load_extension(self_type, extension_name, typer.transformer.state) # restore the self type since we're sharing a type factory typer.known_types['self'] = self_type arg_types = argument_types macro = self_type.add_compiled_macro(klass, name, arg_types) if arguments[-1].kind_of?(BlockArgument) && arguments[-1].optional? arg_types.pop self_type.add_method(name, arg_types, macro) end proxy.__inline__(Noop.new(parent, position)) proxy.infer(typer, expression) end end |
#signature ⇒ Object
306 307 308 309 310 311 312 |
# File 'lib/mirah/ast/intrinsics.rb', line 306 def signature args = argument_types if args.size > 0 && args[-1].block? args[-1] = BiteScript::ASM::Type.getObjectType('duby.lang.compiler.Block') end [nil] + args end |