~singpolyma/dhall-ruby

a2bb88e1cc7881ccab6d792f9e235413b72838ba — Stephen Paul Weber 3 years ago 9d7f8fd
Specialize the visitor since we only use it one place
2 files changed, 23 insertions(+), 35 deletions(-)

M lib/dhall/normalize.rb
D lib/dhall/visitor.rb
M lib/dhall/normalize.rb => lib/dhall/normalize.rb +23 -12
@@ 1,26 1,37 @@
# frozen_string_literal: true

require "dhall/builtins"
require "dhall/visitor"
require "dhall/util"

module Dhall
	module ExpressionVisitor
	class ExpressionVisitor
		ExpressionHash = Util::HashOf.new(
			ValueSemantics::Anything,
			ValueSemantics::Either.new([Expression, nil])
		)

		def self.new(&block)
			Visitor.new(
				Expression                    => block,
				Util::ArrayOf.new(Expression) => lambda do |x|
					x.map(&block)
				end,
				ExpressionHash                => lambda do |x|
					Hash[x.map { |k, v| [k, v.nil? ? v : block[v]] }.sort]
				end
			)
		ExpressionArray = Util::ArrayOf.new(Expression)

		def initialize(&block)
			@block = block
		end

		def visit(expr)
			expr.to_h.each_with_object({}) do |(attr, value), h|
				result = one_visit(value)
				h[attr] = result if result
			end
		end

		def one_visit(value)
			case value
			when Expression
				@block[value]
			when ExpressionArray
				value.map(&@block)
			when ExpressionHash
				Hash[value.map { |k, v| [k, v.nil? ? v : @block[v]] }.sort]
			end
		end
	end


D lib/dhall/visitor.rb => lib/dhall/visitor.rb +0 -23
@@ 1,23 0,0 @@
# frozen_string_literal: true

module Dhall
	class Visitor
		def initialize(callbacks)
			@callbacks = callbacks
		end

		def visit(expr)
			expr.to_h.each_with_object({}) do |(attr, value), h|
				if (callback = callback_for(value))
					h[attr] = callback.call(value)
				end
			end
		end

		protected

		def callback_for(x)
			@callbacks.find { |k, _| k === x }&.last
		end
	end
end