謎's キッチン

謎のひとりごと。Amazon欲しい物リストはこちら: https://www.amazon.co.jp/hz/wishlist/ls/CCPOV7C6JTD2

多段replaceの文字列mixinを使った高速化(3)

次に、実装していきます。まずは、引数の制限を追加します。

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.

えーと…。今の僕には理解できない。続く。