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