Created
March 30, 2015 20:39
-
-
Save Hackerpilot/9708cfa7ce0e259f1600 to your computer and use it in GitHub Desktop.
Issue 14323 test case
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Compiling with -versio=WTF_DMD causes good codegen | |
// Compiling without this version set causes bad codegen | |
struct State | |
{ | |
this(uint breaks, const Token[] tokens, immutable short[] depths, | |
const Config* config, int currentLineLength, int indentLevel) | |
{ | |
import std.math : abs; | |
import core.bitop : popcnt, bsf; | |
import std.algorithm : min, map, sum; | |
// TODO: Figure out what is going on here. | |
version (WTF_DMD) | |
{ | |
enum int remainingCharsMultiplier = 40; | |
enum int newlinePenalty = 800; | |
} | |
else | |
{ | |
immutable int remainingCharsMultiplier = config.columnHardLimit - config.columnSoftLimit; | |
immutable int newlinePenalty = remainingCharsMultiplier * 20; | |
assert(remainingCharsMultiplier == 40); | |
assert(newlinePenalty == 800); | |
} | |
int cost = 0; | |
for (size_t i = 0; i != uint.sizeof * 8; ++i) | |
{ | |
if (((1 << i) & breaks) == 0) | |
continue; | |
immutable b = tokens[i].type; | |
immutable p = abs(depths[i]); | |
immutable bc = breakCost(b) * (p == 0 ? 1 : p * 2); | |
cost += bc; | |
} | |
int ll = currentLineLength; | |
bool solved = true; | |
if (breaks == 0) | |
{ | |
immutable int l = currentLineLength + tokens.map!(a => tokenLength(a)).sum(); | |
cost = l; | |
if (l > config.columnSoftLimit) | |
{ | |
immutable int longPenalty = (l - config.columnSoftLimit) * remainingCharsMultiplier; | |
cost += longPenalty; | |
solved = longPenalty < newlinePenalty; | |
} | |
else | |
solved = true; | |
} | |
else | |
{ | |
size_t i = 0; | |
foreach (_; 0 .. uint.sizeof * 8) | |
{ | |
immutable size_t k = breaks >>> i; | |
immutable bool b = k == 0; | |
immutable size_t j = min(i + bsf(k) + 1, tokens.length); | |
ll += tokens[i .. j].map!(a => tokenLength(a)).sum(); | |
if (ll > config.columnHardLimit) | |
{ | |
solved = false; | |
break; | |
} | |
else if (ll > config.columnSoftLimit) | |
cost += (ll - config.columnSoftLimit) * remainingCharsMultiplier; | |
i = j; | |
ll = indentLevel * config.indentSize; | |
if (b) | |
break; | |
} | |
} | |
cost += popcnt(breaks) * newlinePenalty; | |
this.breaks = breaks; | |
this._cost = cost; | |
this._solved = solved; | |
} | |
uint breaks; | |
private: | |
int _cost; | |
bool _solved; | |
} | |
struct Token | |
{ | |
ubyte type; | |
string text; | |
} | |
int breakCost(ubyte u) pure nothrow @safe @nogc | |
{ | |
switch (u) | |
{ | |
case 50: return 400; | |
case 1: return 0; | |
case 65: return 1000; | |
default: assert(false); | |
} | |
} | |
int tokenLength(ref const Token t) pure @safe @nogc | |
{ | |
switch (t.type) | |
{ | |
case 50: return 1; | |
case 65: return cast(int) t.text.length; | |
case 1: return 2; | |
default: assert (false); | |
} | |
} | |
struct Config | |
{ | |
int columnHardLimit = 120; | |
int columnSoftLimit = 80; | |
int indentSize = 4; | |
} | |
void main() | |
{ | |
import std.range:zip; | |
import std.stdio:writeln; | |
uint breaks = 1; | |
string[] tokenText = [null, "one", null, "two", null, "three", null, "four", null, "five", null, "six", null, "seven", null, "eight", null, "nine", null, "ten", null, "eleven", null, "twelve", null, "thirteen", null, "fourteen"]; | |
immutable ubyte[] tokenTypes = [50, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65]; | |
Token[] tokens = new Token[](tokenText.length); | |
foreach (i; 0 .. tokenText.length) | |
{ | |
tokens[i].text = tokenText[i]; | |
tokens[i].type = tokenTypes[i]; | |
} | |
immutable short[] depths = [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2]; | |
Config c; | |
int currentLineLength = 24; | |
int indentLevel = 1; | |
auto s = State(breaks, tokens, depths, &c, currentLineLength, indentLevel); | |
writeln(s._cost); // 3080 or 2400 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment