class Lisp::Primitive

Attributes

doc[R]
name[R]

Public Class Methods

new(name, arity, doc, special, &implementation) click to toggle source
# File lib/rubylisp/primitive.rb, line 14
def initialize(name, arity, doc, special, &implementation)
  @name = name
  @arity = arity
  @doc = doc
  @special = special
  @implementation = implementation
end
register(name, arity, doc="", special=false, env=Lisp::EnvironmentFrame.global, &implementation) click to toggle source
# File lib/rubylisp/primitive.rb, line 8
def self.register(name, arity, doc="", special=false, env=Lisp::EnvironmentFrame.global, &implementation)
  instance = self.new(name, arity, doc, special, &implementation)
  env.bind(Symbol.named(name), instance)
end

Public Instance Methods

apply_to(args, env) click to toggle source
# File lib/rubylisp/primitive.rb, line 43
def apply_to(args, env)
  return Lisp::Debug.process_error("Wrong number of arguments to #{@name}. Expected #{@arity} but got #{args.length}.", env) unless check_arity(args)

  cooked_args = if @special
                  args
                else
                  Lisp::ConsCell.array_to_list(args.to_a.map {|i| i.evaluate(env)})
                end
  @implementation.call(cooked_args, env)
end
apply_to_without_evaluating(args, env) click to toggle source
# File lib/rubylisp/primitive.rb, line 55
def apply_to_without_evaluating(args, env)
  return Lisp::Debug.process_error("Wrong number of arguments to #{@name}. Expected #{@arity} but got #{args.length}.", env) unless check_arity(args)
  @implementation.call(args, env)
end
check_arity(args) click to toggle source
# File lib/rubylisp/primitive.rb, line 23
def check_arity(args)
  return true if @arity == "*"

  number_of_args = args.length

  @arity.split("|").map do |term|
    m = /^(\d+)$/.match(term)
    return true if m && number_of_args == m[1].to_i

    m = /^>=(\d+)$/.match(term)
    return true if m && number_of_args >= m[1].to_i
    
    m = /^\((\d+),(\d+)\)$/.match(term)
    return true if m && number_of_args >= m[1].to_i && number_of_args <= m[2].to_i
  end

  false
end
primitive?() click to toggle source
# File lib/rubylisp/primitive.rb, line 70
def primitive?
  true
end
special?() click to toggle source
# File lib/rubylisp/primitive.rb, line 75
def special?
  @special
end
to_s() click to toggle source
# File lib/rubylisp/primitive.rb, line 61
def to_s
  if @special
    "<specialform: #{@name}>"
  else
    "<primitive: #{@name}>"
  end
end
type() click to toggle source
# File lib/rubylisp/primitive.rb, line 80
def type
  if @special
    :specialform
  else
    :primitive
  end
end