BCPLのコードを読む日記

EDSACのInSインストラクションの挙動がわからないので、BCPLでの実装を読む。 http://www.cl.cam.ac.uk/users/mr/Edsac/edsac.tgz
BCPLの文法は全然知らないんだけど、類推力を駆使して読み解くのが面白い。

まずここがインストラクションを1個実行するところ。mem!scrが今風に言うとmem[scr]だね。scrはsequence_controlの略。シフトやビット演算は今風。ifがTESTなのとか面白いな。THENとELSEで区切るのはBASIC風だね。で、まあswitch文的なものがあって、肝心のInSのところではsts(addr, rd())をしている。

AND interpret() = VALOF
...
{ // Instruction execution loop
  LET instr = mem!scr
  LET addr  = instr>>1 & #x3FF

  TEST (instr&1)=0 THEN ldrs(addr)
                   ELSE ldrl(addr&#x3FE)

  scr := scr+1
  SWITCHON instr & #b11111_0_0000000000_1 INTO
  { DEFAULT:                     RESULTIS 3

...
    CASE #b00111_0_0000000000_0: stas(addr);          ENDCASE // U n S
    CASE #b00111_0_0000000000_1: stal(addr&#x3FC);    ENDCASE // U n L

    CASE #b01000_0_0000000000_0: sts(addr, rd());     ENDCASE // I n S

stsの定義はこんな感じ

AND sts(a, x) BE mem!a := x & #x1FFFF

rdはテープから1文字入力を読み込んでEDSACの文字コードに変換して返す関数。RESULTISが今風に言うとreturnなんだな。'*t'とか'*n"のアスタリスクは今風に言うとバックスラッシュなんだろうなー。

AND rd() = VALOF
{ LET ch = ?

  UNLESS tape DO
  { writef("*nNo input tape selected*n")
    abort(999)
  }

  ch := rdch()

  SWITCHON ch INTO
  { DEFAULT:  code := asc2ed(ch)
              IF code>=0 RESULTIS code
              writef("Bad ch %n '%c'*n", ch, ch)
              abort(999)
              RESULTIS 0
             
    CASE '*t':
    CASE '*s': 
    CASE '*n': LOOP
  }
} REPEAT