class RubyLisp::Arity

Attributes

body[RW]
required_args[RW]
rest_args[RW]

Public Class Methods

new(ast) click to toggle source
# File lib/rubylisp/function.rb, line 7
def initialize(ast)
  unless list? ast
    raise RuntimeError,
      "Invalid signature #{arity}; expected a list."
  end

  bindings, *body = ast

  unless vector? bindings
    raise RuntimeError,
      "Bindings must be a vector; got #{body.class}."
  end

  bindings.each do |binding|
    unless binding.class == Symbol
      raise RuntimeError,
        "Each binding must be a symbol; got #{binding.class}."
    end
  end

  # bindings is now an array of strings (symbol names)
  bindings = bindings.map(&:value)

  ampersand_indices = bindings.to_list.indices {|x| x == '&'}
  if ampersand_indices.any? {|i| i != bindings.count - 2}
    raise RuntimeError,
      "An '&' can only occur right before the last binding."
  end

  @required_args = bindings.take_while {|binding| binding != '&'}
  @rest_args = bindings.drop_while {|binding| binding != '&'}.drop(1)
  @body = body
end