Skip to content

Commit

Permalink
bug fixes and improvments to TernaryPushdownStrings (issue #236)
Browse files Browse the repository at this point in the history
  • Loading branch information
NivShalmon committed Sep 20, 2016
1 parent 6784650 commit b4b4cd5
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 70 deletions.
@@ -1,7 +1,6 @@
package il.org.spartan.spartanizer.wrings;

import static il.org.spartan.lisp.*;
import static org.eclipse.jdt.core.dom.ASTNode.*;

import java.util.*;

Expand All @@ -17,46 +16,34 @@
import il.org.spartan.spartanizer.engine.*;
import il.org.spartan.spartanizer.wringing.*;

/** convert <code>polite?"Eat your meal.":"Eat your meal, please"
* </code>, <code>polite?"thanks for the meal":"I hated the meal"</code>, and
* <code>a?"abracadabra":"abba"</code> into
/** convert</br>
* <code>polite?"Eat your meal.":"Eat your meal, please"</code>,
* <code>polite?"thanks for the meal":"I hated the meal"</code> </br>
* into </br>
* <code>"Eat your meal"+(polite?".":", please")</code>,
* <code>(polite?"thanks for":"I hated")+"the meal"</code>, and,
* <code>"ab"+(a?"racadabr":"b")+"a"</code>
* <code>(polite?"thanks for":"I hated")+"the meal"</code></br>
* Will not separate words, for example <code> f() ? "True" : "False" </code>
* will not be changed
* @author Dor Ma'ayan
* @author Niv Shalmon
* @since 2016-09-1 */
public final class TernaryPusdownStrings extends ReplaceCurrentNode<ConditionalExpression> implements Kind.Ternarization {
public static Expression replacement(final Expression condition, final Expression then, final Expression elze) {
return iz.is(then, STRING_LITERAL) && iz.is(elze, STRING_LITERAL) ? simplify(condition, az.stringLiteral(then), az.stringLiteral(elze))
: iz.is(then, STRING_LITERAL) && iz.is(elze, INFIX_EXPRESSION) ? simplify(condition, az.stringLiteral(then), az.infixExpression(elze))
: iz.is(then, INFIX_EXPRESSION) && iz.is(elze, STRING_LITERAL)
? simplify(subject.operand(condition).to(PrefixExpression.Operator.NOT), az.stringLiteral(elze), az.infixExpression(then))
: iz.is(then, INFIX_EXPRESSION) && iz.is(elze, INFIX_EXPRESSION)
? simplify(condition, az.infixExpression(then), az.infixExpression(elze)) : null; //
}

static String longer(final String s1, final String s2) {
return s1 == shorter(s1, s2) ? s2 : s1;
}

private static Expression as(final List<Expression> elzeOperands) {
return first(elzeOperands);
}

private static int firstDifference(final String s1, final String s2) {
if (s1 != shorter(s1, s2))
return firstDifference(s2, s1);
assert s1.length() <= s2.length();
if (s1.length() == 0)
return 0;
int $ = 0;
for (int ¢ = 0; ¢ < s1.length(); ++¢) {
if (!Character.isAlphabetic(s1.charAt(¢)) && !Character.isAlphabetic(s2.charAt(¢))//
|| ¢ == s1.length() - 1 && !Character.isAlphabetic(s2.charAt(¢)))
if (!Character.isAlphabetic(first(s1, ¢)) && !Character.isAlphabetic(first(s2, ¢))
|| ¢ == s1.length() - 1 && !Character.isAlphabetic(first(s2, ¢)))
$ = ¢;
if (first(s1, ¢) != first(s2, ¢))
return $;
}
return s1.length();
return s1.length() != s2.length() && Character.isAlphabetic(first(s2, s1.length())) && Character.isAlphabetic(first(s2, s1.length() - 1)) ? 0
: s1.length();
}

/** @param s JD
Expand All @@ -80,22 +67,33 @@ private static StringLiteral getSuffix(final String s, final int i, final ASTNod

// TODO: Yossi: the swap nano
private static int lastDifference(final String s1, final String s2) {
// TODO: Matteo/Ori: the WLOG nano, abbreviated.
if (s1 != shorter(s1, s2))
return lastDifference(s2, s1);
assert s1.length() <= s2.length();
int $ = 0;
for (; $ < s1.length(); ++$)
if (last(s1, $) != last(s2, $))
break;
if ($ == 0)
if (s1.length() == 0)
return 0;
if ($ == s1.length() && s2.length() == s1.length() || $ == s1.length() && !Character.isAlphabetic(s2.charAt(s2.length() - $ - 1)))
return $;
for (int j = s1.length() - $; j < s1.length(); ++j)
if (!Character.isAlphabetic(s1.charAt(j)))
return s1.length() - j;
return 0;
int $ = 0;
for (int ¢ = 0; ¢ < s1.length(); ++¢) {
if (!Character.isAlphabetic(last(s1, ¢)) && !Character.isAlphabetic(last(s2, ¢))
|| ¢ == s1.length() - 1 && !Character.isAlphabetic(last(s2, ¢)))
$ = ¢ + 1;
if (last(s1, ¢) != last(s2, ¢))
return $;
}
return s1.length() != s2.length() && Character.isAlphabetic(last(s2, s1.length())) && Character.isAlphabetic(last(s2, s1.length() - 1)) ? 0 : s1.length();
}

static String longer(final String s1, final String s2) {
return s1 == shorter(s1, s2) ? s2 : s1;
}

public static Expression replacement(final Expression condition, final Expression then, final Expression elze) {
return iz.stringLiteral(then) && iz.stringLiteral(elze) ? simplify(condition, az.stringLiteral(then), az.stringLiteral(elze))
: iz.stringLiteral(then) && iz.infixExpression(elze) ? simplify(condition, az.stringLiteral(then), az.infixExpression(elze))
: iz.infixExpression(then) && iz.stringLiteral(elze)
? simplify(subject.operand(condition).to(PrefixExpression.Operator.NOT), az.stringLiteral(elze), az.infixExpression(then))
: iz.infixExpression(then) && iz.infixExpression(elze) ? simplify(condition, az.infixExpression(then), az.infixExpression(elze))
: null; //
}

private static Expression replacementPrefix(final String then, final String elze, final int commonPrefixIndex, final Expression condition) {
Expand All @@ -113,8 +111,9 @@ private static Expression replacementSuffix(final String then, final String elze
private static InfixExpression replacePrefix(final InfixExpression x, final int i) {
assert x.getOperator() == PLUS2;
final List<Expression> es = extract.allOperands(x);
assert first(es).getNodeType() == STRING_LITERAL;
final StringLiteral l = (StringLiteral) first(es);
final StringLiteral l = az.stringLiteral(first(es));
assert l != null;
assert l.getLiteralValue().length() >= i;
final StringLiteral suffix = getSuffix(l.getLiteralValue(), i, x);
replaceFirst(es, suffix);
return subject.operands(es).to(PLUS2);
Expand All @@ -123,8 +122,9 @@ private static InfixExpression replacePrefix(final InfixExpression x, final int
private static InfixExpression replaceSuffix(final InfixExpression x, final int i) {
assert x.getOperator() == PLUS2;
final List<Expression> es = extract.allOperands(x);
assert last(es).getNodeType() == STRING_LITERAL;
final StringLiteral l = (StringLiteral) last(es);
final StringLiteral l = az.stringLiteral(last(es));
assert l != null;
assert l.getLiteralValue().length() >= i;
final StringLiteral prefix = getPrefix(l.getLiteralValue(), l.getLiteralValue().length() - i, x);
replaceLast(es, prefix);
return subject.operands(es).to(PLUS2);
Expand Down Expand Up @@ -153,28 +153,27 @@ private static Expression simplify(final Expression condition, final StringLiter
final String thenStr = then.getLiteralValue();
assert elze.getOperator() == PLUS2;
final List<Expression> elzeOperands = extract.allOperands(elze);
if (as(elzeOperands).getNodeType() == STRING_LITERAL) {
final String elzeStr = ((StringLiteral) as(elzeOperands)).getLiteralValue();
if (iz.stringLiteral(first(elzeOperands))) {
final String elzeStr = az.stringLiteral(first(elzeOperands)).getLiteralValue();
final int commonPrefixIndex = firstDifference(thenStr, elzeStr);
if (commonPrefixIndex != 0)
return subject.pair(getPrefix(thenStr, commonPrefixIndex, condition), subject.pair(getSuffix(thenStr, commonPrefixIndex, condition), //
replacePrefix(elze, commonPrefixIndex)).toCondition(condition)).to(PLUS2);
}
if (elzeOperands.get(elzeOperands.size() - 1).getNodeType() == STRING_LITERAL) {
final String elzeStr = ((StringLiteral) elzeOperands.get(elzeOperands.size() - 1)).getLiteralValue();
final int commonSuffixIndex = lastDifference(thenStr, elzeStr);
if (commonSuffixIndex != 0) {
final StringLiteral elzePre = getPrefix(elzeStr, elzeStr.length() - commonSuffixIndex, condition);
replaceLast(elzeOperands, elzePre);
return subject
.pair(subject.operand(subject
.pair(getPrefix(thenStr, thenStr.length() - commonSuffixIndex, condition)//
, replaceSuffix(elze, commonSuffixIndex))//
.toCondition(condition)).parenthesis(), getSuffix(thenStr, thenStr.length() - commonSuffixIndex, condition))//
.to(PLUS2);
}
}
return null;
if (!iz.stringLiteral(last(elzeOperands)))
return null;
final String elzeStr = az.stringLiteral(last(elzeOperands)).getLiteralValue();
final int commonSuffixIndex = lastDifference(thenStr, elzeStr);
if (commonSuffixIndex == 0)
return null;
final StringLiteral elzePre = getPrefix(elzeStr, elzeStr.length() - commonSuffixIndex, condition);
replaceLast(elzeOperands, elzePre);
return subject
.pair(subject.operand(subject
.pair(getPrefix(thenStr, thenStr.length() - commonSuffixIndex, condition)//
, replaceSuffix(elze, commonSuffixIndex))//
.toCondition(condition)).parenthesis(), getSuffix(thenStr, thenStr.length() - commonSuffixIndex, condition))//
.to(PLUS2);
}

private static Expression simplify(final Expression condition, final StringLiteral then, final StringLiteral elze) {
Expand All @@ -186,9 +185,9 @@ private static Expression simplifyStrings(final InfixExpression then, final Infi
final List<Expression> thenOperands = extract.allOperands(then);
assert elze.getOperator() == PLUS2;
final List<Expression> elzeOperands = extract.allOperands(elze);
if (first(thenOperands).getNodeType() == STRING_LITERAL && first(elzeOperands).getNodeType() == STRING_LITERAL) {
final String thenStr = ((StringLiteral) first(thenOperands)).getLiteralValue();
final String elzeStr = ((StringLiteral) first(elzeOperands)).getLiteralValue();
if (iz.stringLiteral(first(thenOperands)) && iz.stringLiteral(first(elzeOperands))) {
final String thenStr = az.stringLiteral(first(thenOperands)).getLiteralValue();
final String elzeStr = az.stringLiteral(first(elzeOperands)).getLiteralValue();
final int commonPrefixIndex = firstDifference(thenStr, elzeStr);
if (commonPrefixIndex != 0)
return subject.pair(getPrefix(thenStr, commonPrefixIndex, condition),
Expand All @@ -198,17 +197,16 @@ private static Expression simplifyStrings(final InfixExpression then, final Infi
.toCondition(condition))
.to(PLUS2);
}
if (last(thenOperands).getNodeType() == STRING_LITERAL && last(elzeOperands).getNodeType() == STRING_LITERAL) {
final String thenStr = ((StringLiteral) last(thenOperands)).getLiteralValue();
final String elzeStr = ((StringLiteral) last(thenOperands)).getLiteralValue();
final int commonSuffixIndex = lastDifference(thenStr, elzeStr);
if (commonSuffixIndex != 0)
return subject.pair(subject.operand(subject
if (!iz.stringLiteral(last(thenOperands)) || !iz.stringLiteral(last(elzeOperands)))
return null;
final String thenStr = ((StringLiteral) last(thenOperands)).getLiteralValue();
final String elzeStr = ((StringLiteral) last(thenOperands)).getLiteralValue();
final int commonSuffixIndex = lastDifference(thenStr, elzeStr);
return commonSuffixIndex == 0 ? null
: subject.pair(subject.operand(subject
.pair(replaceSuffix(then, commonSuffixIndex)//
, replaceSuffix(elze, commonSuffixIndex))//
.toCondition(condition)).parenthesis(), getSuffix(thenStr, thenStr.length() - commonSuffixIndex, condition)).to(PLUS2);
}
return null;
}

@Override public String description(@SuppressWarnings("unused") final ConditionalExpression __) {
Expand Down
32 changes: 32 additions & 0 deletions src/test/java/il/org/spartan/spartanizer/wrings/Issue236Test.java
@@ -0,0 +1,32 @@
package il.org.spartan.spartanizer.wrings;

import static il.org.spartan.spartanizer.wrings.TrimmerTestsUtils.*;

import org.junit.*;
import org.junit.runners.*;

/** Unit tests for {@link TernaryPusdownStrings}
* @author Niv Shalmon
* @since 2016 */
@FixMethodOrder(MethodSorters.NAME_ASCENDING) //
@SuppressWarnings({ "static-method", "javadoc" }) //
public class Issue236Test {
@Test public void issue236_01() {
trimmingOf("b ? \"a long string\" : \"another \"+\"long\"+\" string\"")//
.gives("(b ? \"a long\" : \"another \"+\"long\"+\"\") +\" string\"")
.gives("(b ? \"a long\" : \"another \"+\"long\") +\" string\"")
.gives("((b ? \"a \" : \"another \"+\"\") +\"long\")+\" string\"")
.gives("(b ? \"a \" : \"another \"+\"\") +\"long\"+\" string\"")
.gives("(b ? \"a \" : \"another \") +\"long\"+\" string\"")
.gives("((b ? \"a\" : \"another\") + \" \") +\"long\"+\" string\"")
.gives("(b ? \"a\" : \"another\") + \" \" +\"long\"+\" string\"")
.stays();
}

@Test public void issue236_02() {
trimmingOf("b? \"something\" : \"something\"+\" else\"")
.gives("\"something\" + (b? \"\" : \"\"+\" else\")")
.gives("\"something\" + (b? \"\" : \" else\")").stays();
}

}

0 comments on commit b4b4cd5

Please sign in to comment.