名前書き換えスクリプト

TAPLのScala版のソースを呼んでいた訳ですが、変数名や型名を自分に合わせて書き換えたかった。
大量にある、ソースコードIDEリファクタリング機能を持ってしても手に余るので以下のようなコードがあると便利です。

実行する前にバックアップを着実に取ります。
それと、書き換え中の履歴も出来るだけ多く取っておくと良いです。
要するに、何かしらsvnなりgitなりhgなりを使うと良い。
そして、1個ずつ範囲を限定しながら書き換えていきます。
テストが沢山あればあるだけよいでしょう。
なくても、コンパイルが通るとか、ざっと動かしてみるとかでもよいです。
書き換えの作業が必要で大量にある場合は人がやってもミスは出ます。
どちらにしても、ミスはあり得るので履歴を取っておいて、後でおかしくなっている事に気がついたら、履歴を遡って原因を究明します。
原因が人為的ミスならその人に注意を促し、書き換えプログラムに問題があったのならその問題に対応したバージョンの書き換えプログラムに更新します。

こういうスクリプトを使う時の心得としては、出来るだけ範囲を限定した書き換えをして書き換えようと思ったけど辞めたっていうものをリストアップして表示して変更箇所を狭めていく事です。

そうすることで、間違えて書き換えてしまう事が減ります。

こういうスクリプトによる書き換えで1週間コースでバグ有りな変更を3時間くらいで行う事が出来たりします。

このノウハウを伝えるのはなかなか難しくて、良くわからないから手でやりますとか言う人が多くいたりします。

例えば、TyをTに書き換えたいのだけど、Typeは書き換えたくないとかいろいろあります。
書き換えたくないリストとしてignoresに書いておいたりすると便利な訳です。
ファイル名のリストはディレクトリを検索して先に作っておき、範囲を限定するために、このソースだけとか選べるようにしておくと、便利なときは便利です。

あと、コマンドライン引数の有無で書き換えを実行するか、書き換え箇所の出力のみにするとか機能をいろいろ付けると便利です。

でも、正規表現を使っている場合には限界があるので出来れば字句解析くらいしてから書き換えしたいよねとかは思う訳です。例えば文字列のなかにdon'tとかあって、tをeに書き換えるとdon'eになってしまうとかあった訳ですけど。
それでも、作業効率的に言って圧倒的に正規表現で作業した方が良いことはままある訳です。

<?php

$files = array();
$files[] = "./p04arith/core.scala";
$files[] = "./p04arith/demo.scala";
:
$files[] = "./p27fullfomsubref/parser.scala";
$files[] = "./p27fullfomsubref/syntax.scala";
/**/

$datas = array();

foreach($files as $file) {
  $src = file_get_contents($file);
  // $src = "abcdtt1T2 t t t t1 t1 (t3) (T1) (t1_)";

  $changes = array(
   // "t1"=>"e1", "t"=>"e", "t2"=>"e2", "t3"=>"e3",
/*
"ctx" => "c",
"ctx1" => "c1",
"ctx2" => "c2",
*/
/*
"Ty" => "T",
"TyVar" => "TVar",
"TyId" => "TId",
"TyTop" => "TTop",
"TyBot" => "TBot",
"TyArr" => "TArr",
"TyBool" => "TBool",
"TyRecord" => "TRecord",
"TyString" => "TString",
"TyUnit" => "TUnit",
"TyAll" => "TAll",
"TyNat" => "TNat",
"TySome" => "TSome",
"TyVariant" => "TVariant",
"TyVarBind" => "TVarBind",
"TyAbbBind" => "TAbbBind",
"TyRef" => "TRef",
"TySource" => "TSource",
"TySink" => "TSink",
"TyRec" => "TRec",
"TyApp" => "TApp",
"TyAbs" => "TAbs",
*/

"tyX" => "tX",
"tyX1" => "tX1",
"tyT" => "tT",
"tyTi" => "tTi",
"tyTi1" => "tTi1",
"tyTi2" => "tTi2",
"tyTiExpected" => "tTiExpected",
"tyS" => "tS",
"tySi" => "tSi",
"tyT1" => "tT1",
"tyT11" => "tT11",
"tyT12" => "tT12",
"tyT2" => "tT2",
"tyT3" => "tT3",
"tyS1" => "tS1",
"tyS2" => "tS2",
"ty" => "t",
"ty1" => "t1",
"ty2" => "t2",
"ty3" => "t3",
"tyi" => "ti",
"tyi1" => "ti1",
'tyI' => "tI",
'tyC2' => "tC2",
'tyY' => "tY",
'tyU' => "tU",
'tyU1' => "tU1",
"t11" => "e11",
"t21" => "e21",
"tyの型" => "Tの型",
    );
  // $changes = array("t"=>"e",);

$ignores = array(
  "type",
  "typeof",
  "tytermSubst",
  "typeShift",
  "typeSubst",
  "tyBody",
  "tyEqv",
  "tyMap",
  "tyBinder",
  "tyESubstTop",
  'types',
  'tyarith',
  'typeShiftAbove',
  'typeSubstTop',
  'typechecking',
  'typer',
  'typing',
  'tyAbbArgs',
  'tyBound',
);

  if($argv[1]){
    foreach($changes as $s=>$d) {
        $src = preg_replace("/\b(".$s.")\b/", $d, $src)."\n";
    }
  }

  $srcs = explode("\n", $src);
  $dst = "";
  foreach($srcs as $sr) {
    foreach($changes as $s=>$d) {
      
      if (preg_match("/\b".$s."\b/", $sr)>0) {
        $dst .= preg_replace("/\b(".$s.")\b/", "**\$1**", $sr)."\n";
      }
      foreach($ignores as $ss) {
        $sr = preg_replace("/\b(".$ss.")\b/", "", $sr);
      }
      if (preg_match("/\b(".$s."[a-zA-Z0-9_]*)/", $sr,$m)>0) {
        $datas[$m[1]] = 1;
        $rests .= preg_replace("/\b(".$s."[a-zA-Z0-9_]*)/", "**\$1**", $sr)."\n";
      }
    }
  }
  print $dst;

  print "\n======\n";
  print $rests;
  $src = preg_replace("/\n\n+\$/","\n", $src);
  // print $src;

  if($argv[1]=="save") {
    file_put_contents($file, $src);
  }
}

$dt2 = array();
foreach($datas as $k=>$v) {
  $dt2[] = $k;
}

var_export($dt2);