スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

F#で入門 コンパイラ、インタプリタ編 Whitespace(3)

 Whitespaceは「空白」「タブ」「改行」の三種類の文字から構成されたソースを読み込んで、動作するよう定義された、プログラミング言語でした。これのソースを目に見えるように変換する関数visualizeを定義しさらにCommand型の配列に変換する関数makeCArrayを前回定義しました。 
 
空白コード----visualize ------->("tssnsrrt")-------makeCArray------>[|SDup;SPush 5|] 
 
今回は、SDup等を受け取った時にすべき処理をする関数群を定義していきたいと思います。 
処理の結果変化するものはスタックとヒープ領域でそれぞれをListとMapで表現することにします。 
また、これ以外で変化するものの一つがプログラムカウンタでこれは次にCommand型の配列の何番目の要素を処理するかという値を返すことにします。それともう一つサブルーチンの呼び出し処理があるので、それ用にスタックを一つ(これもListで表現することにします。)準備します。 
 
引数をまとめるとつぎのようになります。 
pc     次に実行するcomArrのインデックスを表す 型int 
stcLst スタックを表現するリスト     型list<int> 
heapMap ヒープ領域を表現するMap     型Map<int,int> 
rIndexLst リターンするべきインデックスを収めたリスト 型list<int> 
 
これらをまとめてタプルにして型の別名をつけておきます。 
 
type WState = int*list<int>*Map<int,int>*list<int> 
 
定義する関数は返り値の一部に引数を含む形にします。(こうしておくと、次々に関数を適用していくことが容易に実現可能です。) 
 
とりあえずSDupに対応する関数を書いてみます。 
(SDupはスタックの一番上の値と同じ値をさらにもう一個積む作用でした。) 
 
> let do_SDup ((pc,stcLst,heapMap,rIndexLst):WState) = 
    if List.length stcLst = 0 then failwith(sprintf "index:%d スタックが空でDupできません。" pc) 
    (pc+1,(List.head stcLst)::stcLst,heapMap,rIndexLst);; 
 
val do_SDup : 
  int * int list * Map<int,int> * int list -> 
    int * int list * Map<int,int> * int list 
     
使ってみます。 
例 
>  do_SDup (0,[1;2],Map.empty,[]);; 
val it : int * int list * Map<int,int> * int list = (1, [1; 1; 2], map [], []) 
 
次にSSwapは「スタックの上から0番目の値と1番目の値を入れ替える」という作用ですから次のように定義します。 
 
> let do_SSwap((pc,stcLst,heapMap,rIndexLst):WState) = 
    match stcLst with 
    |h1::h2::tl -> (pc+1,h2::h1::tl,heapMap,rIndexLst) 
    | _-> failwith(sprintf "index:%d スタックの要素の個数が1以下です" pc);; 
 
val do_SSwap : 
  int * int list * Map<int,int> * int list -> 
    int * int list * Map<int,int> * int list 
     
例 
> do_SSwap (0,[3;1;2],Map.empty,[]);; 
val it : int * int list * Map<int,int> * int list = (1, [1; 3; 2], map [], []) 
 
次にSDiscardは「スタックの一番上の値を取り除く」という作用ですから次のように定義します。 
 
> let do_SDiscard ((pc,stcLst,heapMap,rIndexLst):WState) = 
    if List.length stcLst = 0 then failwith(sprintf "index:%d スタックが空でDiscardできません。" pc) 
    (pc+1,(List.tail stcLst),heapMap,rIndexLst);; 
 
val do_SDiscard : 
  int * int list * Map<int,int> * int list -> 
    int * int list * Map<int,int> * int list 
     
例 
> do_SDiscard (0,[3;1;2],Map.empty,[]);; 
val it : int * int list * Map<int,int> * int list = (1, [1; 2], map [], []) 
 
次に「スタックに数値を積む」という作用のSPushですが、これは積む数も引数の一部とする必要があるので次の様に定義します。 
 
> let do_SPush (num:int) ((pc,stcLst,heapMap,rIndexLst):WState) = 
    (pc+1,num::stcLst,heapMap,rIndexLst);; 
 
val do_SPush : 
  int -> 
    int * int list * Map<int,int> * int list -> 
      int * int list * Map<int,int> * int list 
 
例 
> do_SPush 100 (0,[1;2],Map.empty,[]);; 
val it : int * int list * Map<int,int> * int list = 
  (1, [100; 1; 2], map [], []) 
 
次に「スタックの上から数値番目の値と等しい値を一個積む」という作用のSCopyですが次の様に定義します。 
 
> let do_SCopy (n:int) ((pc,stcLst,heapMap,rIndexLst):WState) =     
    if (List.length stcLst) <= n then  failwith(sprintf "index:%d スタックの要素数がたりずにSCopyできません。" pc) 
    let tempArr = Array.ofList stcLst 
    (pc+1,(tempArr.[n])::stcLst,heapMap,rIndexLst);; 
 
val do_SCopy : 
  int -> 
    int * int list * Map<int,int> * int list -> 
      int * int list * Map<int,int> * int list 
 
例 
> do_SCopy 2 (0,[5;4;3],Map.empty,[]);; 
val it : int * int list * Map<int,int> * int list = 
  (1, [3; 5; 4; 3], map [], []) 
   
 
最後にSSlideは「スタックの上から1番目の値から数値番目までの値を取り除く」という作用ですから次のように定義します。 
 
> let do_SSlide (n:int) ((pc,stcLst,heapMap,rIndexLst):WState) = 
    if (List.length stcLst) <= n then  failwith(sprintf "index:%d スタックの要素数がたりずにSSlideできません。" pc) 
    let tempArr = Array.ofList stcLst 
    let slicedArr = tempArr.[(n + 1) ..] 
    let newStcLst = (List.head stcLst)::(List.ofArray slicedArr) 
    (pc+1,newStcLst,heapMap,rIndexLst);; 
 
val do_SSlide : 
  int -> 
    int * int list * Map<int,int> * int list -> 
      int * int list * Map<int,int> * int list 
 
例 
> do_SSlide 1 (0,[5;4;3],Map.empty,[]);; 
val it : int * int list * Map<int,int> * int list = (1, [5; 3], map [], []) 
 
> do_SSlide 2 (0,[5;4;3],Map.empty,[]);; 
val it : int * int list * Map<int,int> * int list = (1, [5], map [], []) 
  
 次回はCommand型の配列を引数にしてから、状態である((pc,stcLst,heapMap,rIndexLst):WState)を変化させていく関数を定義します。 
スポンサーサイト

テーマ : プログラミング
ジャンル : コンピュータ

コメントの投稿

非公開コメント

プロフィール

T GYOUTEN

Author:T GYOUTEN
F#と英単語とフリーソフトと読書に興味があります。
ホームページでフリーソフトも公開しています。どぞ御贔屓に。

最新記事
最新コメント
最新トラックバック
月別アーカイブ
カテゴリ
フリーエリア
フリーエリア
blogram投票ボタン
検索フォーム
RSSリンクの表示
リンク
ブロとも申請フォーム

この人とブロともになる

QRコード
QRコード
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。