M .rubocop.yml => .rubocop.yml +10 -0
@@ 4,6 4,10 @@ AllCops:
Metrics/LineLength:
Max: 80
+Layout/AlignHash:
+ EnforcedHashRocketStyle: table
+ EnforcedColonStyle: table
+
Layout/Tab:
Enabled: false
@@ 37,9 41,15 @@ Style/Documentation:
Style/FormatString:
EnforcedStyle: percent
+Style/RegexpLiteral:
+ AllowInnerSlashes: true
+
Style/StringLiterals:
EnforcedStyle: double_quotes
+Style/StringLiteralsInInterpolation:
+ EnforcedStyle: double_quotes
+
Style/SymbolArray:
EnforcedStyle: brackets
M Gemfile => Gemfile +1 -0
@@ 4,3 4,4 @@ source "https://rubygems.org"
gem "cbor"
gem "value_semantics"
+gem "rubocop"
M lib/dhall/ast.rb => lib/dhall/ast.rb +19 -13
@@ 132,6 132,7 @@ module Dhall
def call(*args)
return super if args.length > 1
+
body.substitute(
Variable.new(name: var),
args.first.shift(1, var, 0)
@@ 311,14 312,14 @@ module Dhall
include(ValueSemantics.for_attributes do
record Expression
input Expression
- type Either(Expression, nil)
+ type Either(Expression, nil)
end)
def map_subexpressions(&block)
with(
record: block[record],
- input: block[input],
- type: type.nil? ? nil : block[type]
+ input: block[input],
+ type: type.nil? ? nil : block[type]
)
end
end
@@ 328,6 329,7 @@ module Dhall
def initialize(record)
raise ArgumentError, "You meant EmptyRecordType?" if record.empty?
+
@record = record
end
@@ 337,6 339,7 @@ module Dhall
def deep_merge_type(other)
return super unless other.is_a?(RecordType)
+
self.class.new(Hash[record.merge(other.record) { |_, v1, v2|
v1.deep_merge_type(v2)
}.sort])
@@ 352,7 355,7 @@ module Dhall
end
class EmptyRecordType < Expression
- include ValueSemantics.for_attributes { }
+ include(ValueSemantics.for_attributes {})
def map_subexpressions
self
@@ 368,6 371,7 @@ module Dhall
def initialize(record)
raise ArgumentError, "You meant EmptyRecord?" if record.empty?
+
@record = record
end
@@ 389,6 393,7 @@ module Dhall
def deep_merge(other)
return super unless other.is_a?(Record)
+
self.class.new(Hash[record.merge(other.record) { |_, v1, v2|
v1.deep_merge(v2)
}.sort])
@@ 396,6 401,7 @@ module Dhall
def merge(other)
return super unless other.is_a?(Record)
+
self.class.new(Hash[record.merge(other.record).sort])
end
@@ 409,7 415,7 @@ module Dhall
end
class EmptyRecord < Expression
- include ValueSemantics.for_attributes { }
+ include(ValueSemantics.for_attributes {})
def map_subexpressions
self
@@ 488,8 494,8 @@ module Dhall
var: k,
type: record.fetch(k),
body: Union.new(
- tag: k,
- value: Variable.new(name: k),
+ tag: k,
+ value: Variable.new(name: k),
alternatives: self.class.new(record.dup.tap { |r| r.delete(k) })
)
)
@@ 533,8 539,8 @@ module Dhall
def map_subexpressions(&block)
with(
predicate: block[predicate],
- then: block[self.then],
- else: block[self.else]
+ then: block[self.then],
+ else: block[self.else]
)
end
end
@@ 590,7 596,7 @@ module Dhall
end)
def to_s
- "#{value >= 0 ? "+" : ""}#{value.to_s}"
+ "#{value >= 0 ? "+" : ""}#{value}"
end
end
@@ 684,9 690,9 @@ module Dhall
def map_subexpressions(&block)
with(
- var: var,
+ var: var,
assign: block[assign],
- type: type.nil? ? nil : block[type]
+ type: type.nil? ? nil : block[type]
)
end
end
@@ 714,7 720,7 @@ module Dhall
def map_subexpressions(&block)
with(
value: block[value],
- type: block[type]
+ type: block[type]
)
end
end
M lib/dhall/binary.rb => lib/dhall/binary.rb +10 -10
@@ 34,7 34,7 @@ module Dhall
class Application
def self.decode(f, *args)
new(
- function: Dhall.decode(f),
+ function: Dhall.decode(f),
arguments: args.map(&Dhall.method(:decode))
)
end
@@ 44,7 44,7 @@ module Dhall
def self.decode(var_or_type, type_or_body, body_or_nil=nil)
if body_or_nil.nil?
new(
- var: "_",
+ var: "_",
type: Dhall.decode(var_or_type),
body: Dhall.decode(type_or_body)
)
@@ 52,7 52,7 @@ module Dhall
raise ArgumentError, "explicit var named _" if var_or_type == "_"
new(
- var: var_or_type,
+ var: var_or_type,
type: Dhall.decode(type_or_body),
body: Dhall.decode(body_or_nil)
)
@@ 94,7 94,7 @@ module Dhall
else
Optional.new(
value: Dhall.decode(value),
- type: type.nil? ? type : Dhall.decode(type)
+ type: type.nil? ? type : Dhall.decode(type)
)
end
end
@@ 104,8 104,8 @@ module Dhall
def self.decode(record, input, type=nil)
new(
record: Dhall.decode(record),
- input: Dhall.decode(input),
- type: type.nil? ? nil : Dhall.decode(type)
+ input: Dhall.decode(input),
+ type: type.nil? ? nil : Dhall.decode(type)
)
end
end
@@ 155,8 155,8 @@ module Dhall
class Union
def self.decode(tag, value, alternatives)
new(
- tag: tag,
- value: Dhall.decode(value),
+ tag: tag,
+ value: Dhall.decode(value),
alternatives: UnionType.decode(alternatives)
)
end
@@ 166,8 166,8 @@ module Dhall
def self.decode(pred, thn, els)
new(
predicate: Dhall.decode(pred),
- then: Dhall.decode(thn),
- else: Dhall.decode(els)
+ then: Dhall.decode(thn),
+ else: Dhall.decode(els)
)
end
end
M lib/dhall/builtins.rb => lib/dhall/builtins.rb +9 -8
@@ 176,16 176,16 @@ module Dhall
else
arg.call(
Application.new(
- function: Variable.new(name: "List"),
+ function: Variable.new(name: "List"),
arguments: [@type]
),
Function.new(
- var: "_",
+ var: "_",
type: @type,
body: Function.new(
var: "_",
type: Application.new(
- function: Variable.new(name: "List"),
+ function: Variable.new(name: "List"),
arguments: [@type.shift(1, "_", 0)]
),
body: Operator::ListConcatenate.new(
@@ 194,7 194,7 @@ module Dhall
),
rhs: Variable.new(name: "_")
)
- ),
+ )
),
EmptyList.new(type: @type)
)
@@ 306,22 306,21 @@ module Dhall
else
arg.call(
Application.new(
- function: Variable.new(name: "Optional"),
+ function: Variable.new(name: "Optional"),
arguments: [@type]
),
Function.new(
- var: "_",
+ var: "_",
type: @type,
body: Optional.new(
value: Variable.new(name: "_"),
- type: @type
+ type: @type
)
),
OptionalNone.new(type: @type)
)
end
end
-
end
class Optional_fold < Builtin
@@ 374,6 373,8 @@ module Dhall
end
end
+ # rubocop:enable Style/ClassAndModuleCamelCase
+
ALL = Hash[constants.map { |c| [c.to_s.tr("_", "/"), const_get(c)] }]
end
end
M lib/dhall/normalize.rb => lib/dhall/normalize.rb +14 -11
@@ 22,6 22,7 @@ module Dhall
class Application
def normalize
return fuse.normalize if fuse
+
normalized = super
return normalized.fuse if normalized.fuse
@@ 35,17 36,18 @@ module Dhall
def fuse
if function.is_a?(Application)
- @fused ||= function.function.fusion(*function.arguments, *arguments)
- return @fused if @fused
+ @fuse ||= function.function.fusion(*function.arguments, *arguments)
+ return @fuse if @fuse
end
- @fused ||= function.fusion(*arguments)
+ @fuse ||= function.fusion(*arguments)
end
end
class Function
def shift(amount, name, min_index)
return super unless var == name
+
with(
type: type.shift(amount, name, min_index),
body: body.shift(amount, name, min_index + 1)
@@ 71,6 73,7 @@ module Dhall
class Variable
def shift(amount, name, min_index)
return self if self.name != name || min_index > index
+
with(index: index + amount)
end
@@ 130,7 133,7 @@ module Dhall
def normalize
normalized = super
if [normalized.lhs, normalized.rhs]
- .any? { |x| x == Natural.new(value: 0) }
+ .any? { |x| x == Natural.new(value: 0) }
Natural.new(value: 0)
elsif normalized.lhs == Natural.new(value: 1)
normalized.rhs
@@ 258,8 261,8 @@ module Dhall
normalized = with(
predicate: pred,
- then: self.then.normalize,
- else: self.else.normalize
+ then: self.then.normalize,
+ else: self.else.normalize
)
if normalized.trivial?
@@ 312,20 315,20 @@ module Dhall
end
def desugar
- lets.reverse.reduce(body) { |inside, let|
+ lets.reverse.reduce(body) do |inside, let|
Application.new(
- function: Function.new(
- var: let.var,
+ function: Function.new(
+ var: let.var,
type: let.type,
body: inside
),
arguments: [let.assign]
)
- }
+ end
end
def shift(amount, name, min_index)
- desugar.shift(amont, name, min_index)
+ desugar.shift(amount, name, min_index)
end
end
M test/test_normalization.rb => test/test_normalization.rb +16 -17
@@ 9,9 9,11 @@ require "dhall/normalize"
DIRPATH = Pathname.new(File.dirname(__FILE__))
UNIT = DIRPATH + "normalization/beta/"
-STANDARD = DIRPATH + 'normalization/standard/'
+STANDARD = DIRPATH + "normalization/standard/"
-class TestParser < Minitest::Test
+# Tests are not the place for abstractions, but for concretions
+# rubocop:disable Metrics/MethodLength
+class TestNormalization < Minitest::Test
Pathname.glob(UNIT + "*A.dhallb").each do |path|
test = path.basename("A.dhallb").to_s
define_method("test_#{test}") do
@@ 23,12 25,13 @@ class TestParser < Minitest::Test
end
Pathname.glob(STANDARD + "**/*A.dhallb").each do |path|
- test = path.relative_path_from(STANDARD).to_s.sub(/A\.dhallb$/, '')
+ test = path.relative_path_from(STANDARD).to_s.sub(/A\.dhallb$/, "")
next if test =~ /prelude\//
next if test =~ /remoteSystems/
next if test =~ /constructorsId$/
next if test =~ /multiline\//
- define_method("test_#{test.gsub(/\//, '_')}") do
+
+ define_method("test_#{test.gsub(/\//, "_")}") do
assert_equal(
Dhall.from_binary(STANDARD + "#{test}B.dhallb"),
Dhall.from_binary(path.read).normalize
@@ 65,29 68,24 @@ class TestParser < Minitest::Test
end
def test_shift_closed
- assert_equal(
- Dhall::Function.new(
- var: "x",
- type: Dhall::Variable.new(name: "Type"),
- body: Dhall::Variable.new(name: "x", index: 0)
- ),
- Dhall::Function.new(
- var: "x",
- type: Dhall::Variable.new(name: "Type"),
- body: Dhall::Variable.new(name: "x", index: 0)
- ).shift(1, "x", 0)
+ expr = Dhall::Function.new(
+ var: "x",
+ type: Dhall::Variable.new(name: "Type"),
+ body: Dhall::Variable.new(name: "x", index: 0)
)
+
+ assert_equal(expr, expr.shift(1, "x", 0))
end
def test_shift_free
assert_equal(
Dhall::Function.new(
- var: "y",
+ var: "y",
type: Dhall::Variable.new(name: "Type"),
body: Dhall::Variable.new(name: "x", index: 1)
),
Dhall::Function.new(
- var: "y",
+ var: "y",
type: Dhall::Variable.new(name: "Type"),
body: Dhall::Variable.new(name: "x", index: 0)
).shift(1, "x", 0)
@@ 124,3 122,4 @@ class TestParser < Minitest::Test
)
end
end
+# rubocop:enable Metrics/MethodLength