M lib/dhall/ast.rb => lib/dhall/ast.rb +99 -0
@@ 20,6 20,57 @@ module Dhall
def to_proc
method(:call).to_proc
end
+
+ def +(other)
+ Operator::Plus.new(lhs: self, rhs: other)
+ end
+
+ def *(other)
+ Operator::Times.new(lhs: self, rhs: other)
+ end
+
+ def <<(other)
+ Operator::TextConcatenate.new(lhs: self, rhs: other)
+ end
+
+ def concat(other)
+ case other
+ when EmptyList
+ self
+ else
+ Operator::ListConcatenate.new(lhs: self, rhs: other)
+ end
+ end
+
+ def &(other)
+ if self == other
+ self
+ elsif other.is_a?(Bool)
+ other & self
+ else
+ Operator::And.new(lhs: self, rhs: other)
+ end
+ end
+
+ def |(other)
+ if self == other
+ self
+ elsif other.is_a?(Bool)
+ other | self
+ else
+ Operator::Or.new(lhs: self, rhs: other)
+ end
+ end
+
+ def dhall_eq(other)
+ if self == other
+ Bool.new(value: true)
+ elsif other.is_a?(Bool)
+ other.dhall_eq(self)
+ else
+ Operator::Equal.new(lhs: self, rhs: other)
+ end
+ end
end
class Application < Expression
@@ 55,6 106,18 @@ module Dhall
def reduce(when_true, when_false)
value ? when_true : when_false
end
+
+ def &(other)
+ reduce(other, with(value: false))
+ end
+
+ def |(other)
+ reduce(with(value: true), other)
+ end
+
+ def dhall_eq(other)
+ reduce(other, super)
+ end
end
class Variable < Expression
@@ 124,6 187,14 @@ module Dhall
def reverse
with(elements: elements.reverse)
end
+
+ def concat(other)
+ if other.is_a?(List) && !other.is_a?(EmptyList)
+ with(elements: elements + other.elements)
+ else
+ super
+ end
+ end
end
class EmptyList < List
@@ 158,6 229,10 @@ module Dhall
def reverse
self
end
+
+ def concat(other)
+ other
+ end
end
class Optional < Expression
@@ 320,6 395,22 @@ module Dhall
value (0..Float::INFINITY)
end)
+ def +(other)
+ if other.is_a?(Natural)
+ with(value: value + other.value)
+ else
+ super
+ end
+ end
+
+ def *(other)
+ if other.is_a?(Natural)
+ with(value: value * other.value)
+ else
+ super
+ end
+ end
+
def to_s
value.to_s
end
@@ 357,6 448,14 @@ module Dhall
include(ValueSemantics.for_attributes do
value ::String
end)
+
+ def <<(other)
+ if other.is_a?(Text)
+ with(value: value + other.value)
+ else
+ super
+ end
+ end
end
class TextLiteral < Expression
M lib/dhall/normalize.rb => lib/dhall/normalize.rb +10 -54
@@ 48,46 48,19 @@ module Dhall
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
+ lhs.normalize | rhs.normalize
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
+ lhs.normalize & rhs.normalize
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
+ lhs.normalize.dhall_eq(rhs.normalize)
end
end
@@ 109,14 82,12 @@ module Dhall
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)
+ if normalized.lhs == Natural.new(value: 0)
normalized.rhs
elsif normalized.rhs == Natural.new(value: 0)
normalized.lhs
else
- normalized
+ normalized.lhs + normalized.rhs
end
end
end
@@ 124,9 95,7 @@ module Dhall
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]
+ if [normalized.lhs, normalized.rhs]
.any? { |x| x == Natural.new(value: 0) }
Natural.new(value: 0)
elsif normalized.lhs == Natural.new(value: 1)
@@ 134,7 103,7 @@ module Dhall
elsif normalized.rhs == Natural.new(value: 1)
normalized.lhs
else
- normalized
+ normalized.lhs * normalized.rhs
end
end
end
@@ 142,32 111,19 @@ module Dhall
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: "")
+ if normalized.lhs == Text.new(value: "")
normalized.rhs
elsif normalized.rhs == Text.new(value: "")
normalized.lhs
else
- normalized
+ normalized.lhs << normalized.rhs
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
+ lhs.normalize.concat(rhs.normalize)
end
end
end