class Riml::AST_Rewriter::ClassDefinitionToFunctions::SuperToSuperclassFunction
rewrites calls to ‘super’ in public/private non-initialize functions
Public Instance Methods
add_superclass_func_ref_to_constructor(superclass)
click to toggle source
# File lib/riml/ast_rewriter.rb, line 790 def add_superclass_func_ref_to_constructor(superclass) super_func_name = superclass_func_name(superclass) assign_node = AssignNode.new('=', DictGetDotNode.new( GetVariableNode.new(nil, ast.constructor_obj_name), [super_func_name] ), CallNode.new( nil, 'function', [ BinaryOperatorNode.new( '.', [ BinaryOperatorNode.new( '.', [ StringNode.new('<SNR>', :s), CallNode.new('s:', 'SID', []), ] ), StringNode.new("_s:#{super_func_name}", :s) ] ) ] ) ) ast.constructor.expressions << assign_node reestablish_parents(ast.constructor) end
match?(node)
click to toggle source
# File lib/riml/ast_rewriter.rb, line 722 def match?(node) return false unless SuperNode === node n = node n = n.parent until DefNode === n || n.nil? return false if n.nil? || ast.constructor == n @function_node = n end
replace(node)
click to toggle source
# File lib/riml/ast_rewriter.rb, line 730 def replace(node) func_scope = 's:' superclass = classes[ast.superclass_full_name] while superclass && !superclass.has_function?(func_scope, superclass_func_name(superclass)) && superclass.superclass? superclass = classes[superclass.superclass_full_name] end superclass_function = superclass.find_function(func_scope, superclass_func_name(superclass)) if superclass.nil? || !superclass_function error_msg = "super was called in class #{ast.full_name} in " \ "function #{@function_node.original_name}, but there are no " \ "functions with this name in that class's superclass hierarchy." error = Riml::InvalidSuper.new(error_msg, node) raise error end node_args = if node.arguments.empty? && !node.with_parens && superclass_function.splat [SplatNode.new(GetVariableNode.new('a:', '000'))] else if @function_node.private_function? node.arguments.unshift GetVariableNode.new(nil, @function_node.parameters.first) end node.arguments end # check if SplatNode is in node_args. If it is, check if the splat # value is equal to splat param. If it is, and we're inside a # private function, we have to add the explicit object (first # parameter to the function we're in) to the splat arg if @function_node.private_function? if (splat_node = node_args.detect { |arg| SplatNode === arg }) self_var = GetVariableNode.new('a:', @function_node.parameters.first) splat_node.expression = BinaryOperatorNode.new('+', [ListNode.wrap(self_var), splat_node.expression]) establish_parents(splat_node.expression) end # call s:ClassA_private_func(args) call_node_name = superclass_func_name(superclass) else # call self.ClassA_public_func(args) call_node_name = DictGetDotNode.new( GetVariableNode.new(nil, 'self'), [superclass_func_name(superclass)] ) end call_node = CallNode.new( nil, call_node_name, node_args ) call_node.super_call = true node.replace_with(call_node) # private functions are NOT extended in constructor function unless @function_node.private_function? add_superclass_func_ref_to_constructor(superclass) end reestablish_parents(@function_node) end
superclass_func_name(superclass)
click to toggle source
# File lib/riml/ast_rewriter.rb, line 786 def superclass_func_name(superclass) "#{superclass.name}_#{@function_node.original_name}" end