Sha256: 6414c00e5ccda1dc44747876eadcfe043d9345f27fc0da608d719bdd11b719b1

Contents?: true

Size: 1.81 KB

Versions: 3

Compression:

Stored size: 1.81 KB

Contents

require "lasp/fn"
require "lasp/macro"
require "lasp/errors"

module Lasp
  class Interpreter
    def self.eval(form, env)
      new.eval(form, env)
    end

    def eval(form, env)
      case form
      when Symbol then resolve_symbol(form, env)
      when Array  then eval_form(form, env)
      else form
      end
    end

    private

    def eval_form(form, env)
      head, *tail = *form

      case head
      when :def   then def_special_form(tail, env)
      when :fn    then fn_special_form(tail, env)
      when :do    then do_special_form(tail, env)
      when :if    then if_special_form(tail, env)
      when :quote then quote_special_form(tail, env)
      when :macro then macro_special_form(tail, env)
      else call_function(head, tail, env)
      end
    end

    def resolve_symbol(symbol, env)
      env.fetch(symbol)
    rescue KeyError
      raise NameError, "#{symbol} is not present in this context"
    end

    def call_function(symbol, args, env)
      fn = eval(symbol, env)

      case fn
      when Macro then eval(fn.(*args), env)
      else fn.(*args.map { |form| eval(form, env) })
      end
    end

    def def_special_form(form, env)
      key, value = form
      fail ArgumentError, "you can only def symbols" unless Symbol === key
      env[key] = eval(value, env)
    end

    def fn_special_form(form, env)
      params, func = form
      Fn.new(params, func, env)
    end

    def do_special_form(form, env)
      form.map { |form| eval(form, env) }.last
    end

    def if_special_form(form, env)
      conditional, true_form, false_form = form
      eval(conditional, env) ? eval(true_form, env) : eval(false_form, env)
    end

    def quote_special_form(form, _)
      form.first
    end

    def macro_special_form(form, env)
      params, func = form
      Macro.new(params, func, env)
    end
  end
end

Version data entries

3 entries across 3 versions & 1 rubygems

Version Path
lasp-0.10.1 lib/lasp/interpreter.rb
lasp-0.10.0 lib/lasp/interpreter.rb
lasp-0.9.0 lib/lasp/interpreter.rb