2017-04-12 86 views
2

在访问一个编译单元时---在给定的条件下 - 我想应用一个转换(使用=>运算符)并计算相同转换应用于给定编译的次数单元。替换+副作用

我能够使用一种“全局模块变量”来执行该操作,但我确信可以在单个访问表达式中组合替换和操作。那可能吗?它使用的是本地变量,并用insert

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

一种方式操作:

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声明与之前的=>箭头具有相同的效果;
  • 由于比赛:=总是成功的,我改变了when条款成一个简单的分配新建分配FY

也有在流氓共享状态信息,其他更复杂的方式,但我个人更喜欢有状态无法逃避的词汇范围的功能。

+0

这真是太棒了。谢谢! –