Skip to content

Commit

Permalink
Fix repeatability test in Navigation#iterate (#126)
Browse files Browse the repository at this point in the history
  • Loading branch information
kputnam committed Jan 13, 2019
1 parent 8dc956b commit 58658da
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 25 deletions.
17 changes: 5 additions & 12 deletions lib/stupidedi/builder/navigation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -453,8 +453,7 @@ def count!(id, *elements)
# @return [Either<Array<Object>>]
def iterate(id, *elements)
a = []
# m = __find(false, id, elements, true)
m = __find(false, id, elements, false)
m = __find(false, id, elements, true)
return m unless m.defined?

while m.defined?
Expand Down Expand Up @@ -487,14 +486,9 @@ def sequence(pattern, *patterns)

# @return [Either<StateMachine>]
def __find(invalid, id, elements, assert_repeatable = false)
reachable = false
matches = []

# Note op.segment_use.nil? is true when searching for ISA,
# GS, and ST, because we can't know the SegmentUse until we
# deconstruct the token and looked up the versions numbers
# in the Config. Nonetheless, we know ISA, GS, and ST can repeat
repeatable = [:ISA, :GS, :ST].include?(id)
reachable = false
repeatable = false
matches = []

@active.each do |zipper|
matched = false
Expand Down Expand Up @@ -522,8 +516,6 @@ def __find(invalid, id, elements, assert_repeatable = false)
state = zipper
value = zipper.node.zipper

repeatable ||= op_.segment_use.try(:repeatable?)

# 1. Move upward (possibly zero times)
op_.pop_count.times do
value = value.up
Expand All @@ -534,6 +526,7 @@ def __find(invalid, id, elements, assert_repeatable = false)
# nodes to move left, but not exactly how many. Instead, we
# know what the InstructionTable is when we get there.
target = zipper.node.instructions.pop(op_.pop_count).drop(op_.drop_count)
repeatable ||= target.matches(filter_tok, true).present?

# 3. If the segment we're searching for belongs in a new subtree,
# but it's not the only segment that might have "opened" that
Expand Down
106 changes: 93 additions & 13 deletions spec/examples/integration/navigating_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

let(:payment) { Fixtures.file("X221-HP835/1-good.txt").first }
let(:claim) { Fixtures.file("X222-HC837/3b-good.txt").first }
let(:drugs) { Fixtures.file("X222-HC837/10a-good.txt").first }

context "unqualified segments" do
end
Expand Down Expand Up @@ -49,11 +50,11 @@
end
end

context "repeatable segments" do
context "repeatable loops" do
specify "can be iterated" do
expect(lambda do
payment.flatmap do |m|
m.iterate(:ISA) do |isa|
payment.flatmap do |isa|
isa.iterate(:ISA) do |_|
raise "didn't expect a second ISA segment"
end
end
Expand All @@ -62,30 +63,109 @@

specify "can be iterated" do
expect(lambda do
payment.flatmap do |m|
m.iterate(:GS) do |gs|
expect(gs.segment.tap do |segment|
expect(segment.node.id).to eq(:GS)
payment.flatmap do |isa|
isa.iterate(:GS) do |gs|
expect(gs.segmentn.tap do |segment|
expect(segment.id).to eq(:GS)
end).to be_defined

gs.iterate(:ST) do |st|
expect(st.segment.tap do |segment|
expect(segment.node.id).to eq(:ST)
expect(st.segmentn.tap do |segment|
expect(segment.id).to eq(:ST)
end).to be_defined
end
end
end
end).not_to raise_error
end

specify "can be iterated" do
expect(lambda do
payment.flatmap do |isa|
isa.iterate(:GS) do |gs|
gs.iterate(:ST) do |st|
st.iterate(:LX) do |lx|
expect(lx.segmentn.fetch.id).to be == :LX
end
end
end
end
end).not_to raise_error
end
end

# N1*PR is not repeatable, but the parser is less strict because there are
# sibling N1 segments (N1*PE); extra segments would be caught in BuilderDsl
context "non-repeatable loops" do
specify "cannot be iterated" do
expect(lambda do
payment.flatmap do |isa|
isa.find(:GS).flatmap do |gs|
gs.find(:ST).flatmap do |st|
st.iterate(:N1, "PR") do |n1|
expect(n1.segmentn.fetch.id).to be == :N1
end
end
end
end
end).not_to raise_error
end
end

# REF*EV is not repeatable, but the parser is less strict because there are
# sibling REF segments (REF*PR); extra segments would be caught in BuilderDsl
context "non-repeatable qualified segments" do
specify "can be iterated" do
expect(lambda do
payment.flatmap do |isa|
isa.find(:GS).flatmap do |gs|
gs.find(:ST).flatmap do |st|
st.iterate(:REF) do |ref|
expect(ref.segmentn.fetch.id).to be == :REF
expect(ref.elementn(1).fetch.value).to be == "EV"
end

st.iterate(:REF, "EV") do |ref|
expect(ref.segmentn.fetch.id).to be == :REF
expect(ref.elementn(1).fetch.value).to be == "EV"
end
end
end
end
end).not_to raise_error
end
end

context "non-repeatable loops" do
specify "cannot be iterated" do
expect(lambda do
drugs.flatmap do |isa|
isa.find(:GS).flatmap do |gs|
gs.find(:ST).flatmap do |st|
st.find(:HL, nil, nil, "22").flatmap do |hl|
hl.find(:CLM).flatmap do |clm|
clm.find(:LX, 2).flatmap do |lx|
lx.iterate(:LIN) do |lin|
expect(lin.segmentn.fetch.id).to be == :LIN
end
end
end
end
end
end
end
end).to raise_error("LIN segment is not repeatable")
end
end

context "non-repeatable segments" do
specify "cannot be iterated" do
expect(lambda do
payment.flatmap do |m|
m.iterate(:GS) do |gs|
gs.iterate(:ST) do |st|
st.iterate(:BHT)
payment.flatmap do |isa|
isa.find(:GS).flatmap do |gs|
gs.find(:ST).flatmap do |st|
st.iterate(:BHT) do |bht|
end
end
end
end
Expand Down

0 comments on commit 58658da

Please sign in to comment.