Skip to content
This repository has been archived by the owner on Jan 27, 2025. It is now read-only.

Commit

Permalink
Merge pull request #83 from metafacture/66-bindScope
Browse files Browse the repository at this point in the history
Don't restrict bind scope to the bound var
  • Loading branch information
fsteeg authored Dec 3, 2021
2 parents 53505a1 + a70a7b8 commit 020c94f
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 18 deletions.
3 changes: 1 addition & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ jobs:
run: ./gradlew build
- name: Install language server
run: ./gradlew installServer
- name: Change directory
run: cd metafix-vsc/
- name: Install fix extension
working-directory: metafix-vsc/
run: npm install
Original file line number Diff line number Diff line change
Expand Up @@ -92,21 +92,33 @@ else if (sub instanceof Unless) {
private void processBind(final Do theDo, final EList<String> params) {
if (theDo.getName().equals("list")) { // TODO impl multiple binds via FixBind enum
final Map<String, String> options = options(theDo.getOptions());
final Record fullRecord = record.shallowClone();

record.findList(options.get("path"), a -> a.forEach(value -> {
// for each value, bind the current record/scope/context to the given var name:
record = new Record();
record.put(options.get("var"), value);

processSubexpressions(theDo.getElements());
record.remove(options.get("var"));

// and remember the things we added while bound (this probably needs some tweaking):
fullRecord.addAll(record);
}));

record = fullRecord;
record.findList(options.get("path"), a -> {
for (int i = 0; i < a.size(); ++i) {
final Value value = a.get(i);
final String var = options.get("var");
// with var -> keep full record in scope, add the var:
if (var != null) {
record.put(var, value);
processSubexpressions(theDo.getElements());
record.remove(var);
}
// w/o var -> use the currently bound value as the record:
else {
if (value.isHash()) {
final Record fullRecord = record;
record = new Record();
record.addAll(value.asHash());
processSubexpressions(theDo.getElements());
a.set(i, new Value(record));
record = fullRecord;
}
else {
// TODO: bind to arrays (if that makes sense) and strings (access with '.')
throw new IllegalStateException("expected hash, got " + value);
}
}
}
});
}
else {
LOG.warn("Unprocessed bind: {}", theDo);
Expand Down
5 changes: 5 additions & 0 deletions metafix/src/main/java/org/metafacture/metafix/Value.java
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,11 @@ private void insert(final InsertMode mode, final String[] fields, final String n
break;
}
}

/*package-private*/ void set(final int index, final Value value) {
list.set(index, value);
}

}

/**
Expand Down
100 changes: 99 additions & 1 deletion metafix/src/test/java/org/metafacture/metafix/MetafixBindTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,104 @@ public void doList() {
});
}

@Test
public void doListFullRecordInScope() {
MetafixTestHelpers.assertFix(streamReceiver, Arrays.asList(
"do list('path': 'name', 'var': 'n')",
" if any_equal('type','book')",
" paste('title','~Book:','n')",
" else",
" paste('title','~Journal:','n')",
" end",
"end",
"retain('title')"),
i -> {
i.startRecord("1");
i.literal("type", "book");
i.literal("name", "A book");
i.endRecord();
i.startRecord("2");
i.literal("type", "journal");
i.literal("name", "A journal");
i.endRecord();
}, o -> {
o.get().startRecord("1");
o.get().literal("title", "Book: A book");
o.get().endRecord();
o.get().startRecord("2");
o.get().literal("title", "Journal: A journal");
o.get().endRecord();
});
}

@Test
public void bindingScopeWithVar() {
MetafixTestHelpers.assertFix(streamReceiver, Arrays.asList(
"do list('path':'foo','var':'loop')",
" copy_field('test','loop.baz')",
" copy_field('loop.bar','loop.qux')",
"end"),
i -> {
i.startRecord("1");
i.startEntity("foo");
i.literal("bar", "1");
i.endEntity();
i.startEntity("foo");
i.literal("bar", "2");
i.endEntity();
i.literal("test", "42");
i.endRecord();
}, (o, f) -> {
o.get().startRecord("1");
o.get().startEntity("foo");
o.get().startEntity("1");
o.get().literal("bar", "1");
o.get().literal("baz", "42");
o.get().literal("qux", "1");
f.apply(1).endEntity();
o.get().startEntity("2");
o.get().literal("bar", "2");
o.get().literal("baz", "42");
o.get().literal("qux", "2");
f.apply(2).endEntity();
o.get().literal("test", "42");
o.get().endRecord();
});
}

@Test
public void bindingScopeWithoutVar() {
MetafixTestHelpers.assertFix(streamReceiver, Arrays.asList(
"do list('path':'foo')",
" copy_field('test','baz')",
" copy_field('bar','qux')",
"end"),
i -> {
i.startRecord("1");
i.startEntity("foo");
i.literal("bar", "1");
i.endEntity();
i.startEntity("foo");
i.literal("bar", "2");
i.endEntity();
i.literal("test", "42");
i.endRecord();
}, (o, f) -> {
o.get().startRecord("1");
o.get().startEntity("foo");
o.get().startEntity("1");
o.get().literal("bar", "1");
o.get().literal("qux", "1");
f.apply(1).endEntity();
o.get().startEntity("2");
o.get().literal("bar", "2");
o.get().literal("qux", "2");
f.apply(2).endEntity();
o.get().literal("test", "42");
o.get().endRecord();
});
}

@Test
public void doListPathWithDots() {
MetafixTestHelpers.assertFix(streamReceiver, Arrays.asList(
Expand Down Expand Up @@ -99,8 +197,8 @@ public void doListPathWithDots() {
@Test
public void doListWithAppendAndLast() {
MetafixTestHelpers.assertFix(streamReceiver, Arrays.asList(
"set_array('author[]')",
"do list('path': 'creator', 'var': 'c')",
" set_array('author[]')",
" copy_field('c.name', 'author[].$append.name')",
" add_field('author[].$last.type', 'Default')",
"end",
Expand Down

0 comments on commit 020c94f

Please sign in to comment.