module Transproc
  # @api private
  class Compiler
    InvalidFunctionNameError = Class.new(StandardError)

    attr_reader :registry, :transformer

    def initialize(registry, transformer = nil)
      @registry = registry
      @transformer = transformer
    end

    def call(ast)
      ast.map(&method(:visit)).reduce(:>>)
    end

    def visit(node)
      id, *rest = node
      public_send(:"visit_#{id}", *rest)
    end

    def visit_fn(node)
      name, rest = node
      args = rest.map { |arg| visit(arg) }

      if registry.contain?(name)
        registry[name, *args]
      elsif transformer.respond_to?(name)
        Function.new(transformer.method(name), name: name, args: args)
      else
        raise InvalidFunctionNameError, "function name +#{name}+ is not valid"
      end
    end

    def visit_arg(arg)
      arg
    end

    def visit_t(node)
      call(node)
    end
  end
end

# frozen_string_literal: true

module Transproc
  # @api private
  class Compiler
    InvalidFunctionNameError = Class.new(StandardError)

    attr_reader :registry, :transformer

    def initialize(registry, transformer = nil)
      @registry = registry
      @transformer = transformer
    end

    def call(ast)
      ast.map(&method(:visit)).reduce(:>>)
    end

    def visit(node)
      id, *rest = node
      public_send(:"visit_#{id}", *rest)
    end

    def visit_fn(node)
      name, rest = node
      args = rest.map { |arg| visit(arg) }

      if registry.contain?(name)
        registry[name, *args]
      elsif transformer.respond_to?(name)
        Function.new(transformer.method(name), name: name, args: args)
      else
        raise InvalidFunctionNameError, "function name +#{name}+ is not valid"
      end
    end

    def visit_arg(arg)
      arg
    end

    def visit_t(node)
      call(node)
    end
  end
end

Add missing frozen_string_literal: true comment
Add missing frozen_string_literal: true comment
