Add and update docs for internal module

This commit is contained in:
Michael Miller 2018-10-22 16:22:35 -06:00
parent 79392fbeff
commit 4e9cf44c2c
4 changed files with 27 additions and 1 deletions

View file

@ -1,6 +1,7 @@
require "./internals/*"
module Spectator
# Utilities and black magic (hacks) employed by the testing framework.
module Internals
end
end

View file

@ -1,14 +1,22 @@
require "./value_wrapper"
module Spectator::Internals
# Collection of test values supplied to examples.
# Each value is labeled by a symbol that the example knows.
# The values also come with a name that can be given to humans.
struct SampleValues
# Creates an empty set of sample values.
def self.empty
new({} of Symbol => Entry)
end
# Creates a collection of sample values.
protected def initialize(@values = {} of Symbol => Entry)
end
# Adds a new value by duplicating the current set and adding to it.
# The new sample values with the additional value is returned.
# The original set of sample values is not modified.
def add(id : Symbol, name : String, value : T) : SampleValues forall T
wrapper = TypedValueWrapper(T).new(value)
SampleValues.new(@values.merge({
@ -16,18 +24,28 @@ module Spectator::Internals
}))
end
# Retrieves the wrapper for a value.
# The symbol for the value is used for retrieval.
def get_wrapper(id : Symbol)
@values[id].wrapper
end
# Retrieves a value.
# The symbol for the value is used for retrieval.
# The value's type must be provided so that the wrapper can be cast.
def get_value(id : Symbol, value_type : T.class) : T forall T
get_wrapper(id).as(TypedValueWrapper(T)).value
end
# Represents a single value in the set.
private struct Entry
# Human-friendly name for the value.
getter name : String
# Wrapper for the value.
getter wrapper : ValueWrapper
# Creates a new value entry.
def initialize(@name, @wrapper)
end
end

View file

@ -1,9 +1,16 @@
require "./value_wrapper"
module Spectator::Internals
# Implementation of a value wrapper for a specific type.
# Instances of this class should be created to wrap values.
# Then the wrapper should be stored as a `ValueWrapper`
# so that the type is deferred to runtime.
# This trick allows the DSL to store values without explicitly knowing their type.
class TypedValueWrapper(T) < ValueWrapper
# Wrapped value.
getter value : T
# Creates a new wrapper for a value.
def initialize(@value : T)
end
end

View file

@ -1,7 +1,7 @@
module Spectator::Internals
# Base class for proxying test values to examples.
# This abstraction is required for inferring types.
# The `DSL#let` macro makes heavy use of this.
# The DSL makes heavy use of this to defer types.
abstract class ValueWrapper
# Retrieves the underlying value.
abstract def value