2017-04-12 18 views
2

コンパイルユニットにアクセスしているときに一定の条件が与えられたときに、変換(=>演算子を使用)を適用して、同じ変換が与えられたコンパイルに適用された回数を数えたいと思います単位。置換+副作用

「グローバルモジュール変数」のようなものを使用してこれを実行することができましたが、1回の訪問式で置換とアクションの両方を組み合わせることは可能です。それは可能ですか?それを行うため

module MultiCatch 

import lang::java::\syntax::Java18; 
import ParseTree; 
import IO; 
import Map; 
import Type; 
import List; 

// sure, I don't like global variables. 
// 
// However I could not find a way to perform both 
// a replacement and count the number of times 
// it was applied in the same compilation unit. 
int numberOfOccurences = 0; 

/** 
* Refactor a try-catch statement to use the 
* MultiCatch construct of Java 7. 
*/ 
public tuple[int, CompilationUnit] refactorMultiCatch(CompilationUnit unit) { 
    numberOfOccurences = 0; 
    CompilationUnit cu = visit(unit) { 
    case (TryStatement)`try <Block b1> <Catches c1>` => (TryStatement)`try <Block b1> <Catches mc>` 
    when mc := computeMultiCatches(c1) 
    }; 
    return <numberOfOccurences, cu>; 
} 

/* 
* Based on a simple notion of similarity, 
* this function calculates the possible 
* occurences of MultiCatch. 
*/ 
private Catches computeMultiCatches(cs){ 
    map [Block, tuple[list[CatchType], VariableDeclaratorId, Block] ] mCatches =(); 
    visit(cs){ 
     case(CatchClause)`catch (<CatchType t> <VariableDeclaratorId vId>) <Block b>` :{ 
     if (b in mCatches){ 
      <ts, vId, blk> = mCatches[b]; 
      ts += t; 
      mCatches[b] = <ts, vId, blk>; 
      numberOfOccurences += 1; 
     } 
     else{ 
      mCatches[b] = <[t], vId, b>; 
     } 
     } 
    } 
    return generateMultiCatches([mCatches[b] | b <- mCatches]); 
} 

/* 
* Creates a syntactic catch clause (either a simple one or 
* a multicatch). 
* 
* This is a recursive definition. The base case expects only 
* one tuple, and than it returns a single catch clause. In the 
* recursive definition, at least two tuples must be passed as 
* arguments, and thus it returns at least two catches clauses 
* (actually, one catch clause for each element in the list) 
*/ 
private Catches generateMultiCatches([<ts, vId, b>]) = { 
    types = parse(#CatchType, intercalate("| ", ts)); 
    return (Catches)`catch(<CatchType types> <VariableDeclaratorId vId>) <Block b>`; 
}; 
private Catches generateMultiCatches([<ts, vId, b>, C*]) = { 
    catches = generateMultiCatches(C); 
    types = parse(#CatchType, intercalate("| ", ts)); 
    return (Catches)`catch(<CatchType types> <VariableDeclaratorId vId>) <Block b> <CatchClause+ catches>`; 
}; 

答えて

2

一つの方法は、ローカル変数とinsert有するブロックを使用している:

module MultiCatch 

import lang::java::\syntax::Java18; 
import ParseTree; 
import IO; 
import Map; 
import Type; 
import List; 

/** 
* Refactor a try-catch statement to use the 
* MultiCatch construct of Java 7. 
*/ 
public tuple[int, CompilationUnit] refactorMultiCatch(CompilationUnit unit) { 
    int numberOfOccurences = 0; /* the type is superfluous */ 
    CompilationUnit cu = visit(unit) { 
    case (TryStatement)`try <Block b1> <Catches c1>` : { 
     numberOfOccurences += 1; 
     mc = computeMultiCatches(c1) 
     insert (TryStatement)`try <Block b1> <Catches mc>`; 
    } 
    }; 

    return <numberOfOccurences, cu>; 
} 
  • {...}ブロックは、複数の文が一致した後に実行されることを可能にします。
  • ローカル変数は、refactorMultiCatchのフレームにのみ存在するようになりました。
  • insertの文は、以前のものと同じ効果を持ちます。
  • 試合:=は常に成功しているので、私はそこラスカルの状態を共有する他のより複雑な方法もあるが、私は個人的に状態はレキシカルスコープを逃れられない持っていることを好むシンプルassigment

when句を変更関数の

+0

これはグレートです。ありがとう! –