次に、実装していきます。まずは、引数の制限を追加します。
string multiReplace(repstrs...)(string s){ /*static */assert(~repstrs.length & 1, "invalid repstrs.length"); mixin(genMultiReplaceCode(s.stringof, [repstrs])); }
バグでstatic assertにするとクラッシュする件。実行時チェックしかできてないけど、まぁいいや。
まずは、最適化を無視して実装していきます。
/* * multiReplace関数のコードを生成します。 */ private string genMultiReplaceCode(string name, string[] repstrs){ string rv; rv ~= "string rv"\n; rv ~= "for(int i;i<"~name~".length;i++){"\n; for(int i;i<repstrs.length>>1;i++){ rv~=" "; if(i) rv ~= "else "; rv ~= "if("~name~".length > i+"~to!(string)(repstrs[i<<1].length)~" && "~name~"[i..i+"~to!(string)(repstrs[i<<1].length)~"] == \""~repstrs[i<<1]~"\")"\n; rv ~= " rv ~= \""~repstrs[(i<<1)+1]~"\";i+="~to!(string)(repstrs[i<<1].length-1)~";"\n; } rv ~= " else"\n; rv ~= " rv ~= " ~ name ~ "[i];"\n; rv ~= "}"\n; rv ~= "return rv;"\n; return rv; }
読みにくくなってまいりました。コンパイルすると何故かコンパイラがセグフォするなぁ。ということで、良い子の見方、-vオプション。
$ rdmd -v -unittest replace.d parse replace semantic replace import object (/usr/src/phobos/object.d) import std.stdio (/usr/src/phobos/std/stdio.d) import std.c.stdio (/usr/src/phobos/std/c/stdio.d) import std.c.stddef (/usr/src/phobos/std/c/stddef.d) import std.c.stdarg (/usr/src/phobos/std/c/stdarg.d) import std.format (/usr/src/phobos/std/format.d) import std.stdarg (/usr/src/phobos/std/stdarg.d) import std.utf (/usr/src/phobos/std/utf.d) import std.contracts (/usr/src/phobos/std/contracts.d) import std.conv (/usr/src/phobos/std/conv.d) import std.string (/usr/src/phobos/std/string.d) import std.c.stdlib (/usr/src/phobos/std/c/stdlib.d) import std.c.string (/usr/src/phobos/std/c/string.d) import std.uni (/usr/src/phobos/std/uni.d) import std.array (/usr/src/phobos/std/array.d) import std.ctype (/usr/src/phobos/std/ctype.d) import std.typetuple (/usr/src/phobos/std/typetuple.d) import std.traits (/usr/src/phobos/std/traits.d) import std.math (/usr/src/phobos/std/math.d) import std.c.math (/usr/src/phobos/std/c/math.d) import std.algorithm (/usr/src/phobos/std/algorithm.d) import std.random (/usr/src/phobos/std/random.d) import std.c.time (/usr/src/phobos/std/c/time.d) import std.process (/usr/src/phobos/std/process.d) import std.c.process (/usr/src/phobos/std/c/process.d) import std.c.linux.linux (/usr/src/phobos/std/c/linux/linux.d) import std.c.linux.linuxextern (/usr/src/phobos/std/c/linux/linuxextern.d) import std.c.linux.pthread (/usr/src/phobos/std/c/linux/pthread.d) import std.intrinsic (/usr/src/phobos/std/intrinsic.d) import std.date (/usr/src/phobos/std/date.d) import std.dateparse (/usr/src/phobos/std/dateparse.d) import std.functional (/usr/src/phobos/std/functional.d) import std.typecons (/usr/src/phobos/std/typecons.d) import std.metastrings (/usr/src/phobos/std/metastrings.d) import std.iterator (/usr/src/phobos/std/iterator.d) import std.system (/usr/src/phobos/std/system.d) import std.gc (/usr/src/phobos/std/gc.d) import gcstats (/usr/src/phobos/gcstats.d) import std.file (/usr/src/phobos/std/file.d) import std.path (/usr/src/phobos/std/path.d) import std.outofmemory (/usr/src/phobos/std/outofmemory.d) import std.regexp (/usr/src/phobos/std/regexp.d) import std.outbuffer (/usr/src/phobos/std/outbuffer.d) import std.bitmanip (/usr/src/phobos/std/bitmanip.d) semantic2 replace semantic3 replace Segmentation fault (core dumped) rdmd: Couldn't compile or execute replace.d.
えーと…。今の僕には理解できない。続く。