class Jsrb::JSStatementContext

Attributes

stacks[R]

Public Class Methods

new() click to toggle source
# File lib/jsrb/js_statement_context.rb, line 7
def initialize
  @var_count = 0
  @stacks = [[]]
end

Public Instance Methods

gen_var_name!() click to toggle source
# File lib/jsrb/js_statement_context.rb, line 12
def gen_var_name!
  @var_count += 1
  "_v#{@var_count}"
end
new_block() { || ... } click to toggle source
# File lib/jsrb/js_statement_context.rb, line 26
def new_block
  _result, statements = in_new_context { yield }
  {
    type: 'BlockStatement',
    body: statements
  }
end
new_expression(object = nil) click to toggle source
# File lib/jsrb/js_statement_context.rb, line 22
def new_expression(object = nil)
  ExprChain.new(self, object)
end
push(*stmt) click to toggle source
# File lib/jsrb/js_statement_context.rb, line 17
def push(*stmt)
  @stacks.last.push(*stmt)
  nil
end
ruby_to_js_ast(rbv) click to toggle source

rubocop:disable Metrics/MethodLength rubocop:disable Metrics/CyclomaticComplexity rubocop:disable Metrics/AbcSize

# File lib/jsrb/js_statement_context.rb, line 37
def ruby_to_js_ast(rbv)
  case rbv
  when ExprChain
    rbv.object
  when Proc
    chainables = rbv.parameters.map do |_type, name|
      new_expression[name.to_s]
    end
    result, statements = in_new_context { rbv.call(*chainables) }
    if result
      statements.push(
        type: 'ReturnStatement',
        argument: ruby_to_js_ast(result)
      )
    end
    {
      type: 'FunctionExpression',
      id: nil,
      params: chainables.map { |arg| ruby_to_js_ast(arg) },
      body: {
        type: 'BlockStatement',
        body: statements
      }
    }
  when Hash
    var_name = gen_var_name!
    statements = rbv.map do |key, v|
      {
        type: 'ExpressionStatement',
        expression: new_expression[var_name][key].set(v).object
      }
    end
    {
      type: 'CallExpression',
      callee: {
        type: 'FunctionExpression',
        id: nil,
        params: [new_expression[var_name].object],
        body: {
          type: 'BlockStatement',
          body: statements.concat(
            [
              {
                type: 'ReturnStatement',
                argument: new_expression[var_name].object
              }
            ]
          )
        }
      },
      arguments: [
        {
          type: 'ObjectExpression',
          properties: []
        }
      ]
    }
  when Array
    {
      type: 'ArrayExpression',
      elements: rbv.map { |v| ruby_to_js_ast(v) }
    }
  when TrueClass, FalseClass, String, NilClass
    build_literal_ast(rbv)
  when Float::INFINITY
    new_expression[:Number][:POSITIVE_INFINITY].object
  when -Float::INFINITY
    new_expression[:Number][:NEGATIVE_INFINITY].object
  when Float
    if rbv.nan?
      new_expression[:Number][:NaN].object
    else
      build_finite_number_ast(rbv)
    end
  when Integer
    build_finite_number_ast(rbv)
  when Symbol
    ruby_to_js_ast(rbv.to_s)
  else
    raise "Can't convert to JavaScript AST from: #{rbv.inspect}"
  end
end

Private Instance Methods

build_finite_number_ast(value) click to toggle source
# File lib/jsrb/js_statement_context.rb, line 132
def build_finite_number_ast(value)
  if value < 0
    {
      type: 'UnaryExpression',
      operator: '-',
      argument: build_literal_ast(-value)
    }
  else
    build_literal_ast(value)
  end
end
build_literal_ast(value) click to toggle source
# File lib/jsrb/js_statement_context.rb, line 144
def build_literal_ast(value)
  {
    type: 'Literal',
    value: value
  }
end
in_new_context() { || ... } click to toggle source

rubocop:enable Metrics/MethodLength rubocop:enable Metrics/CyclomaticComplexity rubocop:enable Metrics/AbcSize

# File lib/jsrb/js_statement_context.rb, line 125
def in_new_context
  @stacks.push([])
  result = yield
  statements = @stacks.pop
  [result, statements]
end