CodeTools::AST << {
ConstantAccess < Node { node_type const field toplevel, field names bytecode: |g| { pos(g) name_list = self.names.map(&:to_sym) first_name = name_list.shift self.toplevel &? ( # The conceptual toplevel in Myco is the Myco namespace first_name case( :Myco, &{ g.push_myco }, :Ruby, &{ g.push_cpath_top }, :Rubinius, &{ g.push_rubinius }, &{ g.push_myco; g.find_const(first_name) } ) ) ?? ( Myco.find_constant_bytecode(g, first_name) ) name_list.each |name| { g.find_const(name) } } ::Myco::SingletonClass << { find_constant_bytecode: |g, name| { g.push_myco g.push_literal(name) g.push_scope g.send(:find_constant, 2) } # TODO: use the try_find_const_fast instruction here, when it is merged into Rubinius. # find_constant_bytecode: |g, name| { # loop_start_label = g.new_label # retry_label = g.new_label # fail_label = g.new_label # done_label = g.new_label # # g.push_rubinius; g.push_literal(name); g.send(:p, 1, true); g.pop # g.push_scope # g.send(:myco_levels, 0) # # TODO: don't dup, iterate without mutating # g.send(:dup, 0) # stack: myco_levels # loop_start_label.set! # g.dup_top # stack: myco_levels, myco_levels # g.send(:pop, 0) # stack: myco_levels, mod # g.dup_top # stack: myco_levels, mod, mod # g.goto_if_nil(fail_label) # stack: myco_levels, mod # g.try_find_const(name) # stack: myco_levels, result # g.dup_top # stack: myco_levels, result, result # g.goto_if_not_undefined(done_label) # stack: myco_levels, undefined # g.pop # stack: myco_levels # g.goto(loop_start_label) # fail_label.set! # stack: myco_levels, mod # g.pop # stack: myco_levels # g.push_myco # stack: myco_levels, Myco # g.push_literal(name) # g.send(:const_get, 1) # stack: myco_levels, result # done_label.set! # stack: myco_levels, result # g.swap; g.pop # stack: result # } } }
}