# frozen_string_literal: true
module Dhall
class Expression
def normalize
map_subexpressions(&:normalize)
end
end
class Application
end
class Function
end
class Forall; end
class Bool
end
class Variable
end
class Operator
class Or
def normalize
normalized = super
if normalized.lhs.is_a?(Bool)
normalized.lhs.reduce(Bool.new(value: true), normalized.rhs)
elsif normalized.rhs.is_a?(Bool)
normalized.rhs.reduce(Bool.new(value: true), normalized.lhs)
elsif normalized.lhs == normalized.rhs
normalized.lhs
else
normalized
end
end
end
class And
def normalize
normalized = super
if normalized.lhs.is_a?(Bool)
normalized.lhs.reduce(normalized.rhs, Bool.new(value: false))
elsif normalized.rhs.is_a?(Bool)
normalized.rhs.reduce(normalized.lhs, Bool.new(value: false))
elsif normalized.lhs == normalized.rhs
normalized.lhs
else
normalized
end
end
end
class Equal
def normalize
normalized = super
if normalized.lhs == Bool.new(value: true)
normalized.rhs
elsif normalized.rhs == Bool.new(value: true)
normalized.lhs
elsif normalized.lhs == normalized.rhs
Bool.new(value: true)
else
normalized
end
end
end
class NotEqual
def normalize
normalized = super
if normalized.lhs == Bool.new(value: false)
normalized.rhs
elsif normalized.rhs == Bool.new(value: false)
normalized.lhs
elsif normalized.lhs == normalized.rhs
Bool.new(value: false)
else
normalized
end
end
end
class Plus
def normalize
normalized = super
if [normalized.lhs, normalized.rhs].all? { |x| x.is_a?(Natural) }
Natural.new(value: normalized.lhs.value + normalized.rhs.value)
elsif normalized.lhs == Natural.new(value: 0)
normalized.rhs
elsif normalized.rhs == Natural.new(value: 0)
normalized.lhs
else
normalized
end
end
end
class Times
def normalize
normalized = super
if [normalized.lhs, normalized.rhs].all? { |x| x.is_a?(Natural) }
Natural.new(value: normalized.lhs.value * normalized.rhs.value)
elsif [normalized.lhs, normalized.rhs]
.any? { |x| x == Natural.new(value: 0) }
Natural.new(value: 0)
elsif normalized.lhs == Natural.new(value: 1)
normalized.rhs
elsif normalized.rhs == Natural.new(value: 1)
normalized.lhs
else
normalized
end
end
end
class TextConcatenate
def normalize
normalized = super
if [normalized.lhs, normalized.rhs].all? { |x| x.is_a?(Text) }
Text.new(value: normalized.lhs.value + normalized.rhs.value)
elsif normalized.lhs == Text.new(value: "")
normalized.rhs
elsif normalized.rhs == Text.new(value: "")
normalized.lhs
else
normalized
end
end
end
class ListConcatenate
def normalize
normalized = super
if [normalized.lhs, normalized.rhs].all? { |x| x.is_a?(List) }
List.new(
elements: normalized.lhs.elements + normalized.rhs.elements
)
elsif normalized.lhs.is_a?(EmptyList)
normalized.rhs
elsif normalized.rhs.is_a?(EmptyList)
normalized.lhs
else
normalized
end
end
end
end
class List
end
class EmptyList
end
class Optional
end
class OptionalNone
end
class Merge
end
class RecordType
end
class Record
end
class RecordFieldAccess
end
class RecordProjection
end
class UnionType
end
class Union
end
class If
def normalize
if (pred = predicate.normalize).is_a?(Bool)
return pred.reduce(self.then, self.else)
end
normalized = with(
predicate: pred,
then: self.then.normalize,
else: self.else.normalize
)
if normalized.trivial?
pred
elsif normalized.then == normalized.else
normalized.then
else
normalized
end
end
def trivial?
self.then == Bool.new(value: true) &&
self.else == Bool.new(value: false)
end
end
class Number
end
class Natural; end
class Integer; end
class Double; end
class Text
end
class TextLiteral
def normalize
chunks = super.chunks.flat_map { |chunk|
chunk.is_a?(TextLiteral) ? chunk.chunks : chunk
}.chunk { |x| x.is_a?(Text) }.flat_map do |(_, group)|
if group.first.is_a?(Text)
[Text.new(value: group.map(&:value).join)]
else
group
end
end
chunks.length == 1 ? chunks.first : with(chunks: chunks)
end
end
class Import
end
class LetBlock
end
class TypeAnnotation
end
end