class SoberSwag::Parser
Parses a *Dry-Types Schema* into a set of nodes we can use to compile. This is mostly because the visitor pattern sucks and catamorphisms are nice.
Do not use this class directly, as it is not part of the public api. Instead, use classes from the {SoberSwag::Compiler} namespace.
Attributes
found[R]
What other types did we find while parsing this type?
Public Class Methods
new(node)
click to toggle source
# File lib/sober_swag/parser.rb, line 9 def initialize(node) @node = node @found = Set.new end
Public Instance Methods
bind(other)
click to toggle source
Call `.to_syntax` on another node, putting any new classes it finds in the list of classes we found in the process.
If you're a big Haskell nerd, then this is >>=.
# File lib/sober_swag/parser.rb, line 84 def bind(other) result = other.to_syntax @found += other.found result end
run_parser()
click to toggle source
# File lib/sober_swag/parser.rb, line 71 def run_parser [to_syntax, found] end
to_syntax()
click to toggle source
Compile to one of our internal nodes. @return [SoberSwag::Nodes::Base] the node that describes this type.
# File lib/sober_swag/parser.rb, line 17 def to_syntax # rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity case @node when Dry::Types::Default # we handle this elsewhere, so bind(Parser.new(@node.type)) when Dry::Types::Array::Member Nodes::List.new(bind(Parser.new(@node.member))) when Dry::Types::Enum Nodes::Enum.new(@node.values) when Dry::Types::Schema Nodes::Object.new( @node.map { |attr| bind(Parser.new(attr)) } ) when Dry::Types::Schema::Key Nodes::Attribute.new( @node.name, @node.required? && !@node.type.default?, bind(Parser.new(@node.type)), @node.meta ) when Dry::Types::Sum left = bind(Parser.new(@node.left)) right = bind(Parser.new(@node.right)) # special case booleans to just return the left value # this is because modeling a boolean as a sum type of # TrueClass and FalseClass is kinda weird, because they're # considered different types instead of different constructors, # which we don't want to do is_bool = [left, right].all? do |e| e.respond_to?(:value) && [TrueClass, FalseClass].include?(e.value) end if is_bool left else Nodes::Sum.new(left, right) end when Dry::Types::Constrained bind(Parser.new(@node.type)) when Dry::Types::Nominal if @node.respond_to?(:type) && @node.type.is_a?(Dry::Types::Constrained) bind(Parser.new(@node.type)) else old_meta = @node.primitive.respond_to?(:meta) ? @node.primitive.meta : {} # start off with the moral equivalent of NodeTree[String] Nodes::Primitive.new(@node.primitive, old_meta.merge(@node.meta)) end else # Inside of this case we have a class that is some user-defined type # We put it in our array of found types, and consider it a primitive @found.add(@node) Nodes::Primitive.new(@node, @node.respond_to?(:meta) ? @node.meta : {}) end end