class Risp::Interpreter

Constants

SPECIAL_FORMS

Attributes

binding[R]
lexer[R]
macros[R]
parser[R]

Public Class Methods

assign_args(symbols, values) click to toggle source
# File lib/risp/interpreter.rb, line 133
def self.assign_args(symbols, values)
  symbols.each_with_index.reduce({}) do |a, (s, i)|
    v = values[i]
    if s.is_a?(Hamster::Vector) && v.is_a?(Enumerable)
      a.merge(assign_args(s, v))
    elsif s.is_a?(Risp::Splat)
      a[s.name] = values.drop(i)
      a
    else
      a[s.name] = v
      a
    end
  end
end
eval(expr, binding, locals, macros) click to toggle source
# File lib/risp/interpreter.rb, line 73
def self.eval(expr, binding, locals, macros)
  case expr
  when Hamster::List
    first = expr.first
    if special = first.is_a?(Risp::Symbol) && SPECIAL_FORMS[first.name]
      special.call(expr.drop(1), binding, locals, macros)
    elsif macro = first.is_a?(Risp::Symbol) && macros[first.name]
      _, *args = expr
      eval(macro.call(*args), binding, locals, macros)
    elsif first.is_a?(Risp::Method)
      receiver, *args = expr.drop(1).map { |x| eval(x, binding, locals, macros) }
      if args.last.is_a?(Proc) && receiver.method(first.name).arity < args.size
        *args, block = args
        receiver.send(first.name, *args, &block)
      else
        receiver.send(first.name, *args)
      end
    else
      fn, *args = expr.map { |x| eval(x, binding, locals, macros) }
      fn.call(*args)
    end
  when Risp::Symbol
    symbol = expr.name
    resolve(symbol, binding, locals, macros)
  when Enumerable
    expr.map { |x| eval(x, binding, locals, macros) }
  else
    expr
  end
end
new() click to toggle source
# File lib/risp/interpreter.rb, line 60
def initialize()
  @binding = {}
  @macros  = {}
  @lexer   = Risp::Lexer.new
  @parser  = Risp::Parser.new
  corelib  = File.read(File.expand_path('core.risp', File.dirname(__FILE__)))
  eval(corelib)
end
resolve(symbol, binding, locals, macros) click to toggle source
# File lib/risp/interpreter.rb, line 117
def self.resolve(symbol, binding, locals, macros)
  if locals.has_key?(symbol)
    locals[symbol]
  elsif binding.has_key?(symbol)
    binding[symbol]
  else
    begin
      symbol.to_s.split('/').reduce(Object) do |c, p|
        c.const_get(p)
      end
    rescue NameError => e
      raise "cannot resolve #{symbol}"
    end
  end
end
unquote(expr, binding, locals, macros) click to toggle source
# File lib/risp/interpreter.rb, line 104
def self.unquote(expr, binding, locals, macros)
  if expr.is_a?(Enumerable) && !expr.is_a?(Risp::Symbol)
    first, second = expr
    if first.is_a?(Risp::Symbol) && first.name == :unquote
      eval(second, binding, locals, macros)
    else
      expr.map { |x| unquote(x, binding, locals, macros) }
    end
  else
    expr
  end
end

Public Instance Methods

eval(code) click to toggle source
# File lib/risp/interpreter.rb, line 69
def eval(code)
  parser.parse(lexer.lex(code)).map { |x| self.class.eval(x, binding, {}, macros) }.last
end