class Orbacle::Builder
Constants
- BuilderError
Attributes
id_generator[R]
Public Class Methods
new(graph, worklist, tree, id_generator)
click to toggle source
# File lib/orbacle/builder.rb, line 16 def initialize(graph, worklist, tree, id_generator) @graph = graph @worklist = worklist @tree = tree @id_generator = id_generator end
Public Instance Methods
process_file(ast, filepath)
click to toggle source
# File lib/orbacle/builder.rb, line 23 def process_file(ast, filepath) initial_context = Context.new(filepath, Selfie.main, Nesting.empty, Context::AnalyzedKlass.new(nil, :public), nil, {}) result = process(ast, initial_context) return result end
Private Instance Methods
add_edges(xs, ys)
click to toggle source
# File lib/orbacle/builder.rb, line 1396 def add_edges(xs, ys) @graph.add_edges(xs, ys) end
add_vertex(v)
click to toggle source
# File lib/orbacle/builder.rb, line 1392 def add_vertex(v) @graph.add_vertex(v) end
build_def_arguments(formal_arguments, context)
click to toggle source
# File lib/orbacle/builder.rb, line 1273 def build_def_arguments(formal_arguments, context) args = [] kwargs = [] blockarg = nil nodes = {} final_context = formal_arguments.reduce(context) do |current_context, arg_ast| arg_name = arg_ast.children[0] maybe_arg_default_expr = arg_ast.children[1] location = build_location_from_ast(current_context, arg_ast) case arg_ast.type when :arg args << GlobalTree::ArgumentsTree::Regular.new(arg_name) nodes[arg_name] = add_vertex(Node.new(:formal_arg, { var_name: arg_name }, location)) current_context.merge_lenv(arg_name => [nodes[arg_name]]) when :optarg args << GlobalTree::ArgumentsTree::Optional.new(arg_name) maybe_arg_default_expr_result = process(maybe_arg_default_expr, current_context) nodes[arg_name] = add_vertex(Node.new(:formal_optarg, { var_name: arg_name }, location)) @graph.add_edge(maybe_arg_default_expr_result.node, nodes[arg_name]) maybe_arg_default_expr_result.context.merge_lenv(arg_name => [nodes[arg_name]]) when :restarg args << GlobalTree::ArgumentsTree::Splat.new(arg_name) nodes[arg_name] = add_vertex(Node.new(:formal_restarg, { var_name: arg_name }, location)) current_context.merge_lenv(arg_name => [nodes[arg_name]]) when :kwarg kwargs << GlobalTree::ArgumentsTree::Regular.new(arg_name) nodes[arg_name] = add_vertex(Node.new(:formal_kwarg, { var_name: arg_name }, location)) current_context.merge_lenv(arg_name => [nodes[arg_name]]) when :kwoptarg kwargs << GlobalTree::ArgumentsTree::Optional.new(arg_name) maybe_arg_default_expr_result = process(maybe_arg_default_expr, current_context) nodes[arg_name] = add_vertex(Node.new(:formal_kwoptarg, { var_name: arg_name }, location)) @graph.add_edge(maybe_arg_default_expr_result.node, nodes[arg_name]) maybe_arg_default_expr_result.context.merge_lenv(arg_name => [nodes[arg_name]]) when :kwrestarg kwargs << GlobalTree::ArgumentsTree::Splat.new(arg_name) nodes[arg_name] = add_vertex(Node.new(:formal_kwrestarg, { var_name: arg_name }, location)) current_context.merge_lenv(arg_name => [nodes[arg_name]]) when :mlhs nested_arg, next_context = build_def_arguments_nested(arg_ast.children, nodes, current_context) args << nested_arg next_context when :blockarg blockarg = arg_name nodes[arg_name] = add_vertex(Node.new(:formal_blockarg, { var_name: arg_name }, location)) current_context.merge_lenv(arg_name => [nodes[arg_name]]) else raise end end return GlobalTree::ArgumentsTree.new(args, kwargs, blockarg), final_context, nodes end
build_def_arguments_nested(arg_asts, nodes, context)
click to toggle source
# File lib/orbacle/builder.rb, line 1329 def build_def_arguments_nested(arg_asts, nodes, context) args = [] final_context = arg_asts.reduce(context) do |current_context, arg_ast| arg_name = arg_ast.children[0] case arg_ast.type when :arg args << GlobalTree::ArgumentsTree::Regular.new(arg_name) nodes[arg_name] = add_vertex(Node.new(:formal_arg, { var_name: arg_name })) current_context.merge_lenv(arg_name => [nodes[arg_name]]) when :restarg args << GlobalTree::ArgumentsTree::Splat.new(arg_name) nodes[arg_name] = add_vertex(Node.new(:formal_restarg, { var_name: arg_name })) current_context.merge_lenv(arg_name => [nodes[arg_name]]) when :mlhs nested_arg, next_context = build_def_arguments_nested(arg_ast.children, nodes, current_context) args << nested_arg next_context else raise end end return GlobalTree::ArgumentsTree::Nested.new(args), final_context end
build_location_from_ast(context, ast)
click to toggle source
# File lib/orbacle/builder.rb, line 1383 def build_location_from_ast(context, ast) if ast.loc Location.new( context.filepath, build_position_range_from_ast(ast), ast.loc.expression.length) end end
common_range(ast, context, inclusive)
click to toggle source
# File lib/orbacle/builder.rb, line 338 def common_range(ast, context, inclusive) range_from_ast = ast.children[0] range_to_ast = ast.children[1] range_node = Node.new(:range, { inclusive: inclusive }, build_location_from_ast(context, ast)) range_from_ast_result = process(range_from_ast, context) from_node = Node.new(:range_from, {}) @graph.add_edge(range_from_ast_result.node, from_node) @graph.add_edge(from_node, range_node) range_to_ast_result = process(range_to_ast, range_from_ast_result.context) to_node = Node.new(:range_to, {}) @graph.add_edge(range_to_ast_result.node, to_node) @graph.add_edge(to_node, range_node) return Result.new(range_node, range_to_ast_result.context) end
define_attr_reader_method(context, ivar_name, location)
click to toggle source
# File lib/orbacle/builder.rb, line 638 def define_attr_reader_method(context, ivar_name, location) ivar_definition_node = @graph.get_ivar_definition_node(context.scope, :"@#{ivar_name}") metod = @tree.add_method( id_generator.call, context.analyzed_klass_id, :"#{ivar_name}", location, context.analyzed_klass.method_visibility, GlobalTree::ArgumentsTree.new([], [], nil)) @graph.store_metod_nodes(metod.id, {}) @graph.add_edge(ivar_definition_node, @graph.get_metod_nodes(metod.id).result) end
define_attr_writer_method(context, ivar_name, location)
click to toggle source
# File lib/orbacle/builder.rb, line 652 def define_attr_writer_method(context, ivar_name, location) ivar_definition_node = @graph.get_ivar_definition_node(context.scope, :"@#{ivar_name}") arg_name = :_attr_writer arg_node = add_vertex(Node.new(:formal_arg, { var_name: arg_name })) metod = @tree.add_method( id_generator.call, context.analyzed_klass_id, :"#{ivar_name}=", location, context.analyzed_klass.method_visibility, GlobalTree::ArgumentsTree.new([GlobalTree::ArgumentsTree::Regular.new(arg_name)], [], nil)) @graph.store_metod_nodes(metod.id, { arg_name => arg_node }) @graph.add_edge(arg_node, ivar_definition_node) @graph.add_edge(ivar_definition_node, @graph.get_metod_nodes(metod.id).result) end
expr_is_class_definition?(expr)
click to toggle source
# File lib/orbacle/builder.rb, line 1261 def expr_is_class_definition?(expr) expr.type == :send && expr.children[0] == Parser::AST::Node.new(:const, [nil, :Class]) && expr.children[1] == :new end
expr_is_module_definition?(expr)
click to toggle source
# File lib/orbacle/builder.rb, line 1267 def expr_is_module_definition?(expr) expr.type == :send && expr.children[0] == Parser::AST::Node.new(:const, [nil, :Module]) && expr.children[1] == :new end
fold_context(exprs, context)
click to toggle source
# File lib/orbacle/builder.rb, line 1373 def fold_context(exprs, context) nodes = [] final_context = exprs.reduce(context) do |current_context, ast_child| child_result = process(ast_child, current_context) nodes << child_result.node child_result.context end return final_context, nodes end
handle_alias(ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 1075 def handle_alias(ast, context) node = add_vertex(Node.new(:nil, {})) return Result.new(node, context) end
handle_and(ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 961 def handle_and(ast, context) handle_binary_operator(:and, ast.children[0], ast.children[1], context) end
handle_array(ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 298 def handle_array(ast, context) node_array = add_vertex(Node.new(:array, {}, build_location_from_ast(context, ast))) final_context, nodes = fold_context(ast.children, context) add_edges(nodes, node_array) return Result.new(node_array, final_context) end
handle_begin(ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 383 def handle_begin(ast, context) final_context, nodes = fold_context(ast.children, context) if ast.children.empty? return Result.new(add_vertex(Node.new(:nil, {}, ast)), context) else return Result.new(nodes.last, final_context) end end
handle_binary_operator(node_type, expr_left, expr_right, context)
click to toggle source
# File lib/orbacle/builder.rb, line 969 def handle_binary_operator(node_type, expr_left, expr_right, context) expr_left_result = process(expr_left, context) expr_right_result = process(expr_right, expr_left_result.context) node_or = add_vertex(Node.new(node_type, {})) @graph.add_edge(expr_left_result.node, node_or) @graph.add_edge(expr_right_result.node, node_or) return Result.new(node_or, expr_right_result.context) end
handle_block(ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 674 def handle_block(ast, context) send_expr = ast.children[0] args_ast = ast.children[1] block_expr = ast.children[2] if send_expr == Parser::AST::Node.new(:send, [nil, :lambda]) send_context = context else send_expr_result = process(send_expr, context) message_send = send_expr_result.data[:message_send] if message_send send_node = send_expr_result.node send_context = send_expr_result.context else return Result.new(Node.new(:nil, {}), context) end end arguments_tree, context_with_args, args_ast_nodes = build_def_arguments(args_ast.children, send_context) # It's not exactly good - local vars defined in blocks are not available outside (?), # but assignments done in blocks are valid. if block_expr block_expr_result = process(block_expr, context_with_args) block_final_node = block_expr_result.node block_result_context = block_expr_result.context else block_final_node = Node.new(:nil, {}) block_result_context = context_with_args end block_result_node = add_vertex(Node.new(:block_result, {})) @graph.add_edge(block_final_node, block_result_node) lamba = @tree.add_lambda(arguments_tree) @graph.store_lambda_nodes(lamba.id, args_ast_nodes, block_result_node) if lambda_ast?(send_expr) lambda_node = add_vertex(Node.new(:lambda, { id: lamba.id })) return Result.new(lambda_node, block_result_context) else message_send.block = Worklist::BlockLambda.new(lamba.id) return Result.new(send_node, block_result_context) end end
handle_bool(_ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 245 def handle_bool(_ast, context) n = add_vertex(Node.new(:bool, {})) Result.new(n, context) end
handle_case(ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 1131 def handle_case(ast, context) expr_cond = ast.children[0] expr_branches = ast.children[1..-1].compact new_context = process(expr_cond, context).context node_case_result = add_vertex(Node.new(:case_result, {})) final_context = expr_branches.reduce(new_context) do |current_context, expr_when| if expr_when.type == :when expr_cond, expr_body = expr_when.children context_after_cond = process(expr_cond, current_context).context if expr_body.nil? @graph.add_edge(Node.new(:nil, {}), node_case_result) context_after_cond else expr_body_result = process(expr_body, context_after_cond) @graph.add_edge(expr_body_result.node, node_case_result) expr_body_result.context end else expr_body_result = process(expr_when, current_context) @graph.add_edge(expr_body_result.node, node_case_result) expr_body_result.context end end return Result.new(node_case_result, final_context) end
handle_casgn(ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 896 def handle_casgn(ast, context) const_prename, const_name, expr = ast.children return handle_dynamic_casgn(ast, context) if !simple_const_prename?(const_prename) const_name_ref = ConstRef.from_full_name(AstUtils.const_prename_and_name_to_string(const_prename, const_name), context.nesting) if expr_is_class_definition?(expr) parent_klass_name_ast = expr.children[2] parent_name_ref = parent_klass_name_ast.nil? ? nil : ConstRef.from_ast(parent_klass_name_ast, context.nesting) klass = @tree.add_class(parent_name_ref) @tree.add_constant( GlobalTree::Constant.new( const_name_ref.name, context.scope.increase_by_ref(const_name_ref).decrease, build_location_from_ast(context, ast), klass.id)) return Result.new(Node.new(:nil, {}), context) elsif expr_is_module_definition?(expr) mod = @tree.add_module @tree.add_constant( GlobalTree::Constant.new( const_name_ref.name, context.scope.increase_by_ref(const_name_ref).decrease, build_location_from_ast(context, ast), mod.id)) return Result.new(Node.new(:nil, {}), context) else @tree.add_constant( GlobalTree::Constant.new( const_name_ref.name, context.scope.increase_by_ref(const_name_ref).decrease, build_location_from_ast(context, ast))) expr_result = process(expr, context) final_node = Node.new(:casgn, { const_ref: const_name_ref }) @graph.add_edge(expr_result.node, final_node) const_name = context.scope.increase_by_ref(const_name_ref).to_const_name node_const_definition = @graph.get_constant_definition_node(const_name.to_string) @graph.add_edge(final_node, node_const_definition) return Result.new(final_node, expr_result.context) end end
handle_changing_visibility(context, new_visibility, arg_exprs)
click to toggle source
# File lib/orbacle/builder.rb, line 587 def handle_changing_visibility(context, new_visibility, arg_exprs) if context.analyzed_klass_id && arg_exprs.empty? final_node = add_vertex(Node.new(:definition_by_id, { id: context.analyzed_klass_id })) return Result.new(final_node, context.with_visibility(new_visibility)) elsif context.analyzed_klass_id methods_to_change_visibility = arg_exprs.map do |arg_expr| [:sym, :str].include?(arg_expr.type) ? arg_expr.children[0] : nil end.compact methods_to_change_visibility.each do |name| @tree.change_method_visibility(context.analyzed_klass_id, name, new_visibility) end final_node = add_vertex(Node.new(:definition_by_id, { id: context.analyzed_klass_id })) return Result.new(final_node, context) else final_node = add_vertex(Node.new(:const, { const_ref: ConstRef.from_full_name("Object", Nesting.empty) })) return Result.new(final_node, context) end end
handle_class(ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 791 def handle_class(ast, context) klass_name_ast, parent_klass_name_ast, klass_body = ast.children klass_name_ref = ConstRef.from_ast(klass_name_ast, context.nesting) parent_name_ref = if parent_klass_name_ast.nil? || !simple_constant?(parent_klass_name_ast) nil elsif simple_constant?(parent_klass_name_ast) ConstRef.from_ast(parent_klass_name_ast, context.nesting) end klass = @tree.add_class(parent_name_ref) @tree.add_constant( GlobalTree::Constant.new(klass_name_ref.name, context.scope.increase_by_ref(klass_name_ref).decrease, build_location_from_ast(context, ast), klass.id)) new_context = context .with_analyzed_klass(klass.id) .with_nesting(context.nesting.increase_nesting_const(klass_name_ref)) .with_selfie(Selfie.klass_from_scope(context.scope)) if klass_body process(klass_body, new_context) end node = add_vertex(Node.new(:nil, {})) return Result.new(node, context) end
handle_complex(_ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 239 def handle_complex(_ast, context) n = add_vertex(Node.new(:complex, {})) Result.new(n, context) end
handle_const(ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 947 def handle_const(ast, context) if simple_constant?(ast) const_ref = ConstRef.from_ast(ast, context.nesting) node = add_vertex(Node.new(:const, { const_ref: const_ref })) return Result.new(node, context) else node = add_vertex(Node.new(:dynamic_const, {})) return Result.new(node, context) end end
handle_custom_attr_accessor_send(context, arg_exprs, ast)
click to toggle source
# File lib/orbacle/builder.rb, line 627 def handle_custom_attr_accessor_send(context, arg_exprs, ast) location = build_location_from_ast(context, ast) ivar_names = arg_exprs.select {|s| [:sym, :str].include?(s.type) }.map {|s| s.children.first }.map(&:to_s) ivar_names.each do |ivar_name| define_attr_reader_method(context, ivar_name, location) define_attr_writer_method(context, ivar_name, location) end return Result.new(Node.new(:nil, {}), context) end
handle_custom_attr_reader_send(context, arg_exprs, ast)
click to toggle source
# File lib/orbacle/builder.rb, line 607 def handle_custom_attr_reader_send(context, arg_exprs, ast) location = build_location_from_ast(context, ast) ivar_names = arg_exprs.select {|s| [:sym, :str].include?(s.type) }.map {|s| s.children.first }.map(&:to_s) ivar_names.each do |ivar_name| define_attr_reader_method(context, ivar_name, location) end return Result.new(Node.new(:nil, {}), context) end
handle_custom_attr_writer_send(context, arg_exprs, ast)
click to toggle source
# File lib/orbacle/builder.rb, line 617 def handle_custom_attr_writer_send(context, arg_exprs, ast) location = build_location_from_ast(context, ast) ivar_names = arg_exprs.select {|s| [:sym, :str].include?(s.type) }.map {|s| s.children.first }.map(&:to_s) ivar_names.each do |ivar_name| define_attr_writer_method(context, ivar_name, location) end return Result.new(Node.new(:nil, {}), context) end
handle_cvar(ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 471 def handle_cvar(ast, context) cvar_name = ast.children.first cvar_definition_node = @graph.get_cvar_definition_node(context.scope, cvar_name) node = Node.new(:cvar, { var_name: cvar_name }, build_location_from_ast(context, ast)) @graph.add_edge(cvar_definition_node, node) return Result.new(node, context) end
handle_cvasgn(ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 451 def handle_cvasgn(ast, context) cvar_name = ast.children[0] expr = ast.children[1] node_cvasgn = add_vertex(Node.new(:cvasgn, { var_name: cvar_name }, build_location_from_ast(context, ast))) if expr expr_result = process(expr, context) @graph.add_edge(expr_result.node, node_cvasgn) context_after_expr = expr_result.context else context_after_expr = context end node_cvar_definition = @graph.get_cvar_definition_node(context.scope, cvar_name) @graph.add_edge(node_cvasgn, node_cvar_definition) return Result.new(node_cvasgn, context_after_expr) end
handle_def(ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 720 def handle_def(ast, context) method_name = ast.children[0] formal_arguments = ast.children[1] method_body = ast.children[2] arguments_tree, arguments_context, arguments_nodes = build_def_arguments(formal_arguments.children, context) metod = @tree.add_method( id_generator.call, context.analyzed_klass_id, method_name, build_location_from_ast(context, ast), context.analyzed_klass.method_visibility, arguments_tree) @graph.store_metod_nodes(metod.id, arguments_nodes) context.with_analyzed_method(metod.id).tap do |context2| if method_body context2.with_selfie(Selfie.instance_from_scope(context2.scope)).tap do |context3| final_node = process(method_body, context3.merge_lenv(arguments_context.lenv)).node @graph.add_edge(final_node, @graph.get_metod_nodes(context3.analyzed_method).result) end else final_node = add_vertex(Node.new(:nil, {})) @graph.add_edge(final_node, @graph.get_metod_nodes(context2.analyzed_method).result) end end node = add_vertex(Node.new(:sym, { value: method_name }, build_location_from_ast(context, ast))) return Result.new(node, context) end
handle_defined(ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 369 def handle_defined(ast, context) _expr = ast.children[0] node = add_vertex(Node.new(:defined, {}, build_location_from_ast(context, ast))) return Result.new(node, context) end
handle_defs(ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 856 def handle_defs(ast, context) method_receiver = ast.children[0] method_name = ast.children[1] formal_arguments = ast.children[2] method_body = ast.children[3] arguments_tree, arguments_context, arguments_nodes = build_def_arguments(formal_arguments.children, context) if context.analyzed_klass_id eigenclass_of_analyzed_definition = @tree.get_eigenclass_of_definition(context.analyzed_klass_id) place_of_definition_id = eigenclass_of_analyzed_definition.id else place_of_definition_id = nil end metod = @tree.add_method( id_generator.call, place_of_definition_id, method_name, build_location_from_ast(context, ast), context.analyzed_klass.method_visibility, arguments_tree) @graph.store_metod_nodes(metod.id, arguments_nodes) context.with_analyzed_method(metod.id).tap do |context2| if method_body context2.with_selfie(Selfie.klass_from_scope(context2.scope)).tap do |context3| final_node = process(method_body, context3.merge_lenv(arguments_context.lenv)).node @graph.add_edge(final_node, @graph.get_metod_nodes(context3.analyzed_method).result) end else final_node = add_vertex(Node.new(:nil, {})) @graph.add_edge(final_node, @graph.get_metod_nodes(context2.analyzed_method).result) end end node = add_vertex(Node.new(:sym, { value: method_name })) return Result.new(node, context) end
handle_dstr(ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 264 def handle_dstr(ast, context) node_dstr = add_vertex(Node.new(:dstr, {}, build_location_from_ast(context, ast))) final_context, nodes = fold_context(ast.children, context) add_edges(nodes, node_dstr) return Result.new(node_dstr, final_context) end
handle_dsym(ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 289 def handle_dsym(ast, context) node_dsym = add_vertex(Node.new(:dsym, {}, build_location_from_ast(context, ast))) final_context, nodes = fold_context(ast.children, context) add_edges(nodes, node_dsym) return Result.new(node_dsym, final_context) end
handle_dynamic_casgn(ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 936 def handle_dynamic_casgn(ast, context) _const_prename, _const_name, expr = ast.children return process(expr, context) end
handle_ensure(ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 1247 def handle_ensure(ast, context) expr_pre = ast.children[0] expr_ensure_body = ast.children[1] node_ensure = add_vertex(Node.new(:ensure, {})) expr_pre_result = process(expr_pre, context) @graph.add_edge(expr_pre_result.node, node_ensure) if expr_pre_result.node expr_ensure_body_result = process(expr_ensure_body, expr_pre_result.context) return Result.new(node_ensure, expr_ensure_body_result.context) end
handle_erange(ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 334 def handle_erange(ast, context) common_range(ast, context, false) end
handle_flipflop(ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 1363 def handle_flipflop(ast, context) Result.new(add_vertex(Node.new(:bool, {})), context) end
handle_float(ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 226 def handle_float(ast, context) value = one(ast.children) n = add_vertex(Node.new(:float, { value: value })) Result.new(n, context) end
handle_for(ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 1117 def handle_for(ast, context) expr_asgn = ast.children[0] expr_collection = ast.children[1] expr_body = ast.children[2] collection_result = process(expr_collection, context) final_context = process(expr_body, collection_result.context).context node = add_vertex(Node.new(:for, {})) add_edges(collection_result.node, node) return Result.new(node, final_context) end
handle_gvar(ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 497 def handle_gvar(ast, context) gvar_name = ast.children.first gvar_definition_node = @graph.get_gvar_definition_node(gvar_name) node = add_vertex(Node.new(:gvar, { var_name: gvar_name }, build_location_from_ast(context, ast))) @graph.add_edge(gvar_definition_node, node) return Result.new(node, context) end
handle_gvasgn(ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 482 def handle_gvasgn(ast, context) gvar_name = ast.children[0] expr = ast.children[1] node_gvasgn = add_vertex(Node.new(:gvasgn, { var_name: gvar_name }, build_location_from_ast(context, ast))) expr_result = process(expr, context) @graph.add_edge(expr_result.node, node_gvasgn) node_gvar_definition = @graph.get_gvar_definition_node(gvar_name) @graph.add_edge(node_gvasgn, node_gvar_definition) return Result.new(node_gvasgn, expr_result.context) end
handle_hash(ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 753 def handle_hash(ast, context) node_hash_keys = add_vertex(Node.new(:hash_keys, {})) node_hash_values = add_vertex(Node.new(:hash_values, {})) node_hash = add_vertex(Node.new(:hash, {})) @graph.add_edge(node_hash_keys, node_hash) @graph.add_edge(node_hash_values, node_hash) final_context = ast.children.reduce(context) do |current_context, ast_child| case ast_child.type when :pair hash_key, hash_value = ast_child.children hash_key_result = process(hash_key, current_context) hash_value_result = process(hash_value, hash_key_result.context) @graph.add_edge(hash_key_result.node, node_hash_keys) @graph.add_edge(hash_value_result.node, node_hash_values) hash_value_result.context when :kwsplat kwsplat_expr = ast_child.children[0] kwsplat_expr_result = process(kwsplat_expr, context) node_unwrap_hash_keys = Node.new(:unwrap_hash_keys, {}) node_unwrap_hash_values = Node.new(:unwrap_hash_values, {}) @graph.add_edge(kwsplat_expr_result.node, node_unwrap_hash_keys) @graph.add_edge(kwsplat_expr_result.node, node_unwrap_hash_values) @graph.add_edge(node_unwrap_hash_keys, node_hash_keys) @graph.add_edge(node_unwrap_hash_values, node_hash_values) kwsplat_expr_result.context else raise ArgumentError.new(ast) end end return Result.new(node_hash, final_context) end
handle_if(ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 980 def handle_if(ast, context) expr_cond = ast.children[0] expr_iftrue = ast.children[1] expr_iffalse = ast.children[2] expr_cond_result = process(expr_cond, context) if expr_iftrue expr_iftrue_result = process(expr_iftrue, expr_cond_result.context) node_iftrue = expr_iftrue_result.node context_after_iftrue = expr_iftrue_result.context else node_iftrue = add_vertex(Node.new(:nil, {})) context_after_iftrue = context end if expr_iffalse expr_iffalse_result = process(expr_iffalse, expr_cond_result.context) node_iffalse = expr_iffalse_result.node context_after_iffalse = expr_iffalse_result.context else node_iffalse = add_vertex(Node.new(:nil, {})) context_after_iffalse = context end node_if_result = add_vertex(Node.new(:if_result, {})) @graph.add_edge(node_iftrue, node_if_result) @graph.add_edge(node_iffalse, node_if_result) return Result.new(node_if_result, expr_cond_result.context.with_merged_lenvs(context_after_iftrue.lenv, context_after_iffalse.lenv)) end
handle_int(ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 219 def handle_int(ast, context) value = one(ast.children) n = add_vertex(Node.new(:int, { value: value })) Result.new(n, context) end
handle_irange(ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 330 def handle_irange(ast, context) common_range(ast, context, true) end
handle_ivar(ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 404 def handle_ivar(ast, context) ivar_name = ast.children.first ivar_definition_node = if context.selfie.klass? @graph.get_class_level_ivar_definition_node(context.scope, ivar_name) elsif context.selfie.instance? @graph.get_ivar_definition_node(context.scope, ivar_name) elsif context.selfie.main? @graph.get_main_ivar_definition_node(ivar_name) else raise end node = Node.new(:ivar, { var_name: ivar_name }, build_location_from_ast(context, ast)) @graph.add_edge(ivar_definition_node, node) return Result.new(node, context) end
handle_ivasgn(ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 423 def handle_ivasgn(ast, context) ivar_name = ast.children[0] expr = ast.children[1] node_ivasgn = add_vertex(Node.new(:ivasgn, { var_name: ivar_name }, build_location_from_ast(context, ast))) if expr expr_result = process(expr, context) @graph.add_edge(expr_result.node, node_ivasgn) context_after_expr = expr_result.context else context_after_expr = context end ivar_definition_node = if context.selfie.klass? @graph.get_class_level_ivar_definition_node(context.scope, ivar_name) elsif context.selfie.instance? @graph.get_ivar_definition_node(context_after_expr.scope, ivar_name) elsif context.selfie.main? @graph.get_main_ivar_definition_node(ivar_name) else raise end @graph.add_edge(node_ivasgn, ivar_definition_node) return Result.new(node_ivasgn, context_after_expr) end
handle_loop_operator(ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 1175 def handle_loop_operator(ast, context) return Result.new(Node.new(:loop_operator, {}), context) end
handle_lvar(ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 392 def handle_lvar(ast, context) var_name = ast.children[0] node_lvar = add_vertex(Node.new(:lvar, { var_name: var_name }, build_location_from_ast(context, ast))) context.lenv_fetch(var_name).each do |var_definition_node| @graph.add_edge(var_definition_node, node_lvar) end return Result.new(node_lvar, context) end
handle_lvasgn(ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 202 def handle_lvasgn(ast, context) var_name = ast.children[0] expr = ast.children[1] node_lvasgn = add_vertex(Node.new(:lvasgn, { var_name: var_name }, build_location_from_ast(context, ast))) if expr expr_result = process(expr, context) @graph.add_edge(expr_result.node, node_lvasgn) final_context = expr_result.context.merge_lenv(var_name => [node_lvasgn]) else final_context = context.merge_lenv(var_name => [node_lvasgn]) end return Result.new(node_lvasgn, final_context) end
handle_masgn(ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 1037 def handle_masgn(ast, context) mlhs_expr = ast.children[0] rhs_expr = ast.children[1] rhs_expr_result = process(rhs_expr, context) node_rhs = rhs_expr_result.node context_after_rhs = rhs_expr_result.context mlhs_result = handle_mlhs_for_masgn(mlhs_expr, context, rhs_expr) return mlhs_result end
handle_match_current_line(ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 1359 def handle_match_current_line(ast, context) Result.new(add_vertex(Node.new(:bool, {})), context) end
handle_match_with_lvasgn(ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 1355 def handle_match_with_lvasgn(ast, context) return Result.new(add_vertex(Node.new(:int, {})), context) end
handle_mlhs_for_masgn(ast, context, rhs_expr)
click to toggle source
# File lib/orbacle/builder.rb, line 1050 def handle_mlhs_for_masgn(ast, context, rhs_expr) result_node = add_vertex(Node.new(:array, {})) i = 0 final_context = ast.children.reduce(context) do |current_context, ast_child| if ast_child.type == :mlhs new_rhs_expr = Parser::AST::Node.new(:send, [rhs_expr, :[], Parser::AST::Node.new(:int, [i])]) ast_child_result = handle_mlhs_for_masgn(ast_child, current_context, new_rhs_expr) node_child = ast_child_result.node context_after_child = ast_child_result.context else new_ast_child = ast_child.append(Parser::AST::Node.new(:send, [rhs_expr, :[], Parser::AST::Node.new(:int, [i])])) new_ast_child_result = process(new_ast_child, current_context) node_child = new_ast_child_result.node context_after_child = new_ast_child_result.context end @graph.add_edge(node_child, result_node) i += 1 context_after_child end return Result.new(result_node, final_context) end
handle_module(ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 817 def handle_module(ast, context) module_name_ast = ast.children[0] module_body = ast.children[1] module_name_ref = ConstRef.from_ast(module_name_ast, context.nesting) mod = @tree.add_module @tree.add_constant( GlobalTree::Constant.new( module_name_ref.name, context.scope.increase_by_ref(module_name_ref).decrease, build_location_from_ast(context, ast), mod.id)) if module_body context .with_analyzed_klass(mod.id) .with_nesting(context.nesting.increase_nesting_const(module_name_ref)).tap do |context2| process(module_body, context2) end end return Result.new(Node.new(:nil, {}), context) end
handle_nil(ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 251 def handle_nil(ast, context) n = add_vertex(Node.new(:nil, {}, build_location_from_ast(context, ast))) return Result.new(n, context) end
handle_or(ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 965 def handle_or(ast, context) handle_binary_operator(:or, ast.children[0], ast.children[1], context) end
handle_preexe(ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 1367 def handle_preexe(ast, context) body = ast.children[0] body_result = process(body, context) Result.new(add_vertex(Node.new(:nil, {})), body_result.context) end
handle_rational(_ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 233 def handle_rational(_ast, context) n = add_vertex(Node.new(:rational, {})) Result.new(n, context) end
handle_ref(ast, context, node_type)
click to toggle source
# File lib/orbacle/builder.rb, line 357 def handle_ref(ast, context, node_type) ref = if node_type == :backref ast.children[0].to_s[1..-1] elsif node_type == :nthref ast.children[0].to_s else raise end node = add_vertex(Node.new(node_type, { ref: ref }, build_location_from_ast(context, ast))) return Result.new(node, context) end
handle_regexp(ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 318 def handle_regexp(ast, context) expr_nodes = ast.children[0..-2] regopt = ast.children[-1] node_regexp = Node.new(:regexp, { regopt: regopt.children }, build_location_from_ast(context, ast)) final_context, nodes = fold_context(expr_nodes, context) add_edges(nodes, node_regexp) return Result.new(node_regexp, final_context) end
handle_resbody(ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 1179 def handle_resbody(ast, context) error_array_expr = ast.children[0] assignment_expr = ast.children[1] rescue_body_expr = ast.children[2] error_array_expr ||= Parser::AST::Node.new(:array, [Parser::AST::Node.new(:const, [nil, :StandardError])]) error_array_expr_result = process(error_array_expr, context) unwrap_node = add_vertex(Node.new(:unwrap_error_array, {})) @graph.add_edge(error_array_expr_result.node, unwrap_node) context_after_errors = error_array_expr_result.context context_after_assignment = if assignment_expr assignment_expr_result = process(assignment_expr, context_after_errors) @graph.add_edge(unwrap_node, assignment_expr_result.node) if unwrap_node assignment_expr_result.context else context end if rescue_body_expr rescue_body_expr_result = process(rescue_body_expr, context_after_assignment) node_rescue_body = rescue_body_expr_result.node final_context = rescue_body_expr_result.context else node_rescue_body = add_vertex(Node.new(:nil, {})) final_context = context end return Result.new(node_rescue_body, final_context) end
handle_rescue(ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 1210 def handle_rescue(ast, context) try_expr = ast.children[0] resbody = ast.children[1] elsebody = ast.children[2] if try_expr try_expr_result = process(try_expr, context) node_try = try_expr_result.node context_after_try = try_expr_result.context else node_try = add_vertex(Node.new(:nil, {})) context_after_try = context end resbody_result = process(resbody, context_after_try) node_resbody = resbody_result.node context_after_resbody = resbody_result.context node = add_vertex(Node.new(:rescue, {})) @graph.add_edge(node_resbody, node) if elsebody elsebody_result = process(elsebody, context_after_try) node_else = elsebody_result.node context_after_else = elsebody_result.context @graph.add_edge(node_else, node) return Result.new(node, context_after_try.with_merged_lenvs(context_after_resbody.lenv, context_after_else.lenv)) else @graph.add_edge(node_try, node) return Result.new(node, context_after_resbody) end end
handle_retry(ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 1243 def handle_retry(ast, context) return Result.new(add_vertex(Node.new(:retry, {})), context) end
handle_return(ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 1014 def handle_return(ast, context) exprs = ast.children if exprs.size == 0 node_expr = add_vertex(Node.new(:nil, {})) final_context = context elsif exprs.size == 1 expr_result = process(exprs[0], context) node_expr = expr_result.node final_context = expr_result.context else node_expr = add_vertex(Node.new(:array, {})) final_context, nodes = fold_context(ast.children, context) add_edges(nodes, node_expr) end if context.analyzed_method @graph.add_edge(node_expr, @graph.get_metod_nodes(context.analyzed_method).result) end return Result.new(node_expr, final_context) end
handle_sclass(ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 839 def handle_sclass(ast, context) self_name = ast.children[0] sklass_body = ast.children[1] new_context = if self_name == Parser::AST::Node.new(:self) && context.analyzed_klass_id eigenclass_of_analyzed_definition = @tree.get_eigenclass_of_definition(context.analyzed_klass_id) context .with_nesting(context.nesting.increase_nesting_self) .with_analyzed_klass(eigenclass_of_analyzed_definition.id) else context end process(sklass_body, new_context) return Result.new(Node.new(:nil, {}), context) end
handle_self(ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 669 def handle_self(ast, context) node = add_vertex(Node.new(:self, { selfie: context.selfie }, build_location_from_ast(context, ast))) return Result.new(node, context) end
handle_send(ast, context, csend)
click to toggle source
# File lib/orbacle/builder.rb, line 527 def handle_send(ast, context, csend) obj_expr = ast.children[0] message_name = ast.children[1] arg_exprs = ast.children[2..-1] return transform_symbol_shorthand(obj_expr, message_name, arg_exprs, csend, context) if transform_symbol_shorthand_applies?(arg_exprs) if obj_expr.nil? obj_node = add_vertex(Node.new(:self, { selfie: context.selfie })) obj_context = context else expr_result = process(obj_expr, context) obj_node = expr_result.node obj_context = expr_result.context end final_context, call_arg_nodes, block_node = prepare_argument_nodes(obj_context, arg_exprs) return handle_changing_visibility(context, message_name, arg_exprs) if obj_expr.nil? && [:public, :protected, :private].include?(message_name) return handle_custom_attr_reader_send(context, arg_exprs, ast) if obj_expr.nil? && message_name == :attr_reader return handle_custom_attr_writer_send(context, arg_exprs, ast) if obj_expr.nil? && message_name == :attr_writer return handle_custom_attr_accessor_send(context, arg_exprs, ast) if obj_expr.nil? && message_name == :attr_accessor call_obj_node = add_vertex(Node.new(:call_obj, {})) @graph.add_edge(obj_node, call_obj_node) call_result_node = add_vertex(Node.new(:call_result, { csend: csend })) message_send = Worklist::MessageSend.new(message_name, call_obj_node, call_arg_nodes, call_result_node, block_node, build_location_from_ast(context, ast)) @worklist.add_message_send(message_send) return Result.new(call_result_node, final_context, { message_send: message_send }) end
handle_splat(ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 307 def handle_splat(ast, context) expr = ast.children[0] expr_result = process(expr, context) node_splat = Node.new(:splat_array, {}, build_location_from_ast(context, ast)) @graph.add_edge(expr_result.node, node_splat) return Result.new(node_splat, expr_result.context) end
handle_str(ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 257 def handle_str(ast, context) value = ast.children[0] n = add_vertex(Node.new(:str, { value: value }, build_location_from_ast(context, ast))) return Result.new(n, context) end
handle_super(ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 1080 def handle_super(ast, context) arg_exprs = ast.children final_context, call_arg_nodes, block_node = prepare_argument_nodes(context, arg_exprs) call_result_node = add_vertex(Node.new(:call_result, {})) super_send = Worklist::SuperSend.new(call_arg_nodes, call_result_node, block_node, final_context.analyzed_method, build_location_from_ast(context, ast)) @worklist.add_message_send(super_send) return Result.new(call_result_node, final_context, { message_send: super_send }) end
handle_sym(ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 282 def handle_sym(ast, context) value = ast.children[0] n = add_vertex(Node.new(:sym, { value: value }, build_location_from_ast(context, ast))) return Result.new(n, context) end
handle_undef(ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 377 def handle_undef(ast, context) node = add_vertex(Node.new(:nil, {})) Result.new(node, context) end
handle_while(ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 1105 def handle_while(ast, context) expr_cond = ast.children[0] expr_body = ast.children[1] new_context = process(expr_cond, context).context final_context = process(expr_body, new_context).context node = add_vertex(Node.new(:nil, {})) return Result.new(node, final_context) end
handle_xstr(ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 273 def handle_xstr(ast, context) node_xstr = add_vertex(Node.new(:xstr, {}, build_location_from_ast(context, ast))) final_context, nodes = fold_context(ast.children, context) add_edges(nodes, node_xstr) return Result.new(node_xstr, final_context) end
handle_yield(ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 1161 def handle_yield(ast, context) exprs = ast.children final_context, call_arg_nodes, _block_node = prepare_argument_nodes(context, exprs) result_node = add_vertex(Node.new(:yield_result, {})) if context.analyzed_method method_nodes = @graph.get_metod_nodes(context.analyzed_method) method_nodes.yields << Graph::Yield.new(call_arg_nodes, result_node) end return Result.new(result_node, final_context) end
handle_zsuper(ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 1093 def handle_zsuper(ast, context) call_result_node = add_vertex(Node.new(:call_result, {})) if context.analyzed_method method_nodes = @graph.get_metod_nodes(context.analyzed_method) zsuper = Graph::ZSuper.new(call_result_node, nil) method_nodes.zsupers << zsuper end return Result.new(call_result_node, context, { message_send: zsuper }) end
lambda_ast?(send_expr)
click to toggle source
# File lib/orbacle/builder.rb, line 1404 def lambda_ast?(send_expr) send_expr == Parser::AST::Node.new(:send, [nil, :lambda]) end
one(arr)
click to toggle source
# File lib/orbacle/builder.rb, line 1408 def one(arr) arr[0] end
prepare_argument_nodes(context, arg_exprs)
click to toggle source
# File lib/orbacle/builder.rb, line 561 def prepare_argument_nodes(context, arg_exprs) call_arg_nodes = [] block_node = nil final_context = arg_exprs.reduce(context) do |current_context, ast_child| case ast_child.type when :block_pass block_pass_result = process(ast_child.children[0], current_context) block_node = Worklist::BlockNode.new(block_pass_result.node) block_pass_result.context when :splat ast_child_result = process(ast_child.children[0], current_context) call_arg_node = add_vertex(Node.new(:call_splatarg, {})) call_arg_nodes << call_arg_node @graph.add_edge(ast_child_result.node, call_arg_node) ast_child_result.context else ast_child_result = process(ast_child, current_context) call_arg_node = add_vertex(Node.new(:call_arg, {})) call_arg_nodes << call_arg_node @graph.add_edge(ast_child_result.node, call_arg_node) ast_child_result.context end end return final_context, call_arg_nodes, block_node end
process(ast, context)
click to toggle source
# File lib/orbacle/builder.rb, line 32 def process(ast, context) return Result.new(nil, context) if ast.nil? process_result = case ast.type # primitives when :int handle_int(ast, context) when :float handle_float(ast, context) when :rational handle_rational(ast, context) when :complex handle_complex(ast, context) when :true handle_bool(ast, context) when :false handle_bool(ast, context) when :nil handle_nil(ast, context) when :str handle_str(ast, context) when :dstr handle_dstr(ast, context) when :xstr handle_xstr(ast, context) when :sym handle_sym(ast, context) when :dsym handle_dsym(ast, context) when :regexp handle_regexp(ast, context) # arrays when :array handle_array(ast, context) when :splat handle_splat(ast, context) # ranges when :irange handle_irange(ast, context) when :erange handle_erange(ast, context) # hashes when :hash handle_hash(ast, context) # local variables when :lvar handle_lvar(ast, context) when :lvasgn handle_lvasgn(ast, context) # global variables when :gvar handle_gvar(ast, context) when :gvasgn handle_gvasgn(ast, context) # instance variables when :ivar handle_ivar(ast, context) when :ivasgn handle_ivasgn(ast, context) when :self handle_self(ast, context) when :back_ref handle_ref(ast, context, :backref) when :nth_ref handle_ref(ast, context, :nthref) when :defined? handle_defined(ast, context) when :undef handle_undef(ast, context) when :begin handle_begin(ast, context) when :kwbegin handle_begin(ast, context) when :cvar handle_cvar(ast, context) when :cvasgn handle_cvasgn(ast, context) when :send handle_send(ast, context, false) when :csend handle_send(ast, context, true) when :block handle_block(ast, context) when :def handle_def(ast, context) when :defs handle_defs(ast, context) when :class handle_class(ast, context) when :sclass handle_sclass(ast, context) when :module handle_module(ast, context) when :casgn handle_casgn(ast, context) when :const handle_const(ast, context) when :and handle_and(ast, context) when :or handle_or(ast, context) when :if handle_if(ast, context) when :return handle_return(ast, context) when :masgn handle_masgn(ast, context) when :alias handle_alias(ast, context) when :super handle_super(ast, context) when :zsuper handle_zsuper(ast, context) when :case handle_case(ast, context) when :yield handle_yield(ast, context) when :while then handle_while(ast, context) when :until then handle_while(ast, context) when :while_post then handle_while(ast, context) when :until_post then handle_while(ast, context) when :for then handle_for(ast, context) when :break then handle_loop_operator(ast, context) when :next then handle_loop_operator(ast, context) when :redo then handle_loop_operator(ast, context) when :rescue then handle_rescue(ast, context) when :resbody then handle_resbody(ast, context) when :retry then handle_retry(ast, context) when :ensure then handle_ensure(ast, context) when :op_asgn then handle_op_asgn(ast, context) when :or_asgn then handle_or_asgn(ast, context) when :and_asgn then handle_and_asgn(ast, context) when :match_with_lvasgn then handle_match_with_lvasgn(ast, context) when :match_current_line then handle_match_current_line(ast, context) when :iflipflop then handle_flipflop(ast, context) when :eflipflop then handle_flipflop(ast, context) when :preexe then handle_preexe(ast, context) when :postexe then handle_preexe(ast, context) else raise ArgumentError.new(ast.type) end if process_result.node && !process_result.node.location process_result.node.location = build_location_from_ast(context, ast) end return process_result rescue BuilderError raise rescue => e puts "Error #{e} happened when parsing file #{context.filepath}" puts ast puts e.backtrace raise BuilderError end
simple_const_prename?(const_prename)
click to toggle source
# File lib/orbacle/builder.rb, line 941 def simple_const_prename?(const_prename) const_prename.nil? || (const_prename.type == :const && simple_const_prename?(const_prename.children[0])) || const_prename.type == :cbase end
simple_constant?(c)
click to toggle source
# File lib/orbacle/builder.rb, line 1400 def simple_constant?(c) c.type == :const && simple_const_prename?(c.children[0]) end
transform_symbol_shorthand(obj_expr, message_name, arg_exprs, csend, context)
click to toggle source
# File lib/orbacle/builder.rb, line 508 def transform_symbol_shorthand(obj_expr, message_name, arg_exprs, csend, context) block_message_block_pass = arg_exprs.last block_message_name = block_message_block_pass.children.last.children.last normal_arg_exprs = arg_exprs[0..-2] send_ast_type = csend ? :csend : :send send_ast = Parser::AST::Node.new(send_ast_type, [obj_expr, message_name, *normal_arg_exprs]) arg_ast = Parser::AST::Node.new(:args, [Parser::AST::Node.new(:arg, [:__orbacle__x])]) block_body_ast = Parser::AST::Node.new(:send, [Parser::AST::Node.new(:lvar, [:__orbacle__x]), block_message_name]) block_ast = Parser::AST::Node.new(:block, [send_ast, arg_ast, block_body_ast]) handle_block(block_ast, context) end
transform_symbol_shorthand_applies?(arg_exprs)
click to toggle source
# File lib/orbacle/builder.rb, line 520 def transform_symbol_shorthand_applies?(arg_exprs) arg_exprs.last && arg_exprs.last.type == :block_pass && arg_exprs.last.children.last && arg_exprs.last.children.last.type == :sym end