Refactoring: extracted split method into intervals
This commit is contained in:
+38
-37
@@ -23,7 +23,7 @@ import org.jetbrains.org.objectweb.asm.tree.*
|
|||||||
import java.util.Comparator
|
import java.util.Comparator
|
||||||
import java.util.Collections
|
import java.util.Collections
|
||||||
|
|
||||||
public abstract class CoveringTryCatchNodeProcessor<T: IntervalWithHandler>() {
|
public abstract class CoveringTryCatchNodeProcessor<T : IntervalWithHandler> where T : SplittableInterval<T> {
|
||||||
|
|
||||||
public val tryBlocksMetaInfo: IntervalMetaInfo<T> = IntervalMetaInfo();
|
public val tryBlocksMetaInfo: IntervalMetaInfo<T> = IntervalMetaInfo();
|
||||||
|
|
||||||
@@ -32,18 +32,6 @@ public abstract class CoveringTryCatchNodeProcessor<T: IntervalWithHandler>() {
|
|||||||
public val coveringFromInnermost: List<T>
|
public val coveringFromInnermost: List<T>
|
||||||
get() = tryBlocksMetaInfo.currentIntervals.reverse()
|
get() = tryBlocksMetaInfo.currentIntervals.reverse()
|
||||||
|
|
||||||
protected fun addNewTryCatchNode(newInfo: T) {
|
|
||||||
tryBlocksMetaInfo.addNewInterval(newInfo)
|
|
||||||
}
|
|
||||||
|
|
||||||
protected fun addNewLocalVar(newInfo: LocalVarNodeWrapper) {
|
|
||||||
localVarsMetaInfo.addNewInterval(newInfo)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun remapStartLabel(oldStart: LabelNode, remapped: T) {
|
|
||||||
tryBlocksMetaInfo.remapStartLabel(oldStart, remapped)
|
|
||||||
}
|
|
||||||
|
|
||||||
public fun getStartNodes(label: LabelNode): List<T> {
|
public fun getStartNodes(label: LabelNode): List<T> {
|
||||||
return tryBlocksMetaInfo.intervalStarts.get(label)
|
return tryBlocksMetaInfo.intervalStarts.get(label)
|
||||||
}
|
}
|
||||||
@@ -86,19 +74,14 @@ public abstract class CoveringTryCatchNodeProcessor<T: IntervalWithHandler>() {
|
|||||||
|
|
||||||
public abstract fun instructionIndex(inst: AbstractInsnNode): Int
|
public abstract fun instructionIndex(inst: AbstractInsnNode): Int
|
||||||
|
|
||||||
|
|
||||||
public fun getNonEmptyNodes(): List<T> {
|
|
||||||
return tryBlocksMetaInfo.getNonEmptyNodes()
|
|
||||||
}
|
|
||||||
|
|
||||||
public fun sortTryCatchBlocks() {
|
public fun sortTryCatchBlocks() {
|
||||||
val comp = Comparator { t1: T, t2: T ->
|
val comp = Comparator { t1: T, t2: T ->
|
||||||
var result = instructionIndex(t1.handler) - instructionIndex(t2.handler)
|
var result = instructionIndex(t1.handler) - instructionIndex(t2.handler)
|
||||||
if (result == 0) {
|
if (result == 0) {
|
||||||
result = instructionIndex(t1.startLabel) - instructionIndex(t2.startLabel)
|
result = instructionIndex((t1 as Interval).startLabel) - instructionIndex((t2 as Interval).startLabel)
|
||||||
if (result == 0) {
|
if (result == 0) {
|
||||||
assert(false, "Error: support multicatch finallies!")
|
assert(false, "Error: support multicatch finallies!")
|
||||||
result = instructionIndex(t1.endLabel) - instructionIndex(t2.endLabel)
|
result = instructionIndex((t1 as Interval).endLabel) - instructionIndex((t2 as Interval).endLabel)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result
|
result
|
||||||
@@ -108,7 +91,7 @@ public abstract class CoveringTryCatchNodeProcessor<T: IntervalWithHandler>() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class IntervalMetaInfo<T: Interval> {
|
class IntervalMetaInfo<T : Interval> {
|
||||||
|
|
||||||
val intervalStarts = LinkedListMultimap.create<LabelNode, T>()
|
val intervalStarts = LinkedListMultimap.create<LabelNode, T>()
|
||||||
|
|
||||||
@@ -131,7 +114,18 @@ class IntervalMetaInfo<T: Interval> {
|
|||||||
|
|
||||||
fun remapEndLabel(oldEnd: LabelNode, remapped: T) {
|
fun remapEndLabel(oldEnd: LabelNode, remapped: T) {
|
||||||
intervalEnds.remove(oldEnd, remapped)
|
intervalEnds.remove(oldEnd, remapped)
|
||||||
intervalEnds.put(remapped.startLabel, remapped)
|
intervalEnds.put(remapped.endLabel, remapped)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun split(interval: SplittableInterval<T>, by : Interval, keepStart: Boolean): SplittedPair<T> {
|
||||||
|
val splittedPair = interval.split(by, keepStart)
|
||||||
|
if (!keepStart) {
|
||||||
|
remapStartLabel((splittedPair.newPart as Interval).startLabel, splittedPair.patchedPart)
|
||||||
|
} else {
|
||||||
|
remapEndLabel((splittedPair.newPart as Interval).endLabel, splittedPair.patchedPart)
|
||||||
|
}
|
||||||
|
addNewInterval(splittedPair.newPart)
|
||||||
|
return splittedPair
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun getNonEmptyNodes(): List<T> {
|
public fun getNonEmptyNodes(): List<T> {
|
||||||
@@ -152,7 +146,7 @@ class IntervalMetaInfo<T: Interval> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class DefaultProcessor(val node: MethodNode) : CoveringTryCatchNodeProcessor<TryCatchBlockNodeWrapper>() {
|
public class DefaultProcessor(val node: MethodNode) : CoveringTryCatchNodeProcessor<TryCatchBlockNodeInfo>() {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
node.tryCatchBlocks.forEach { addTryNode(it) }
|
node.tryCatchBlocks.forEach { addTryNode(it) }
|
||||||
@@ -160,11 +154,11 @@ public class DefaultProcessor(val node: MethodNode) : CoveringTryCatchNodeProces
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun addLocalVarNode(it: LocalVariableNode) {
|
fun addLocalVarNode(it: LocalVariableNode) {
|
||||||
addNewLocalVar(LocalVarNodeWrapper(it))
|
localVarsMetaInfo.addNewInterval(LocalVarNodeWrapper(it))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addTryNode(node: TryCatchBlockNode) {
|
fun addTryNode(node: TryCatchBlockNode) {
|
||||||
addNewTryCatchNode(TryCatchBlockNodeWrapper(node))
|
tryBlocksMetaInfo.addNewInterval(TryCatchBlockNodeInfo(node, false))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun instructionIndex(inst: AbstractInsnNode): Int {
|
override fun instructionIndex(inst: AbstractInsnNode): Int {
|
||||||
@@ -172,20 +166,27 @@ public class DefaultProcessor(val node: MethodNode) : CoveringTryCatchNodeProces
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class LocalVarNodeWrapper(val node: LocalVariableNode) : Interval {
|
public class LocalVarNodeWrapper(val node: LocalVariableNode) : Interval, SplittableInterval<LocalVarNodeWrapper> {
|
||||||
override val startLabel: LabelNode
|
override val startLabel: LabelNode
|
||||||
get() = node.start
|
get() = node.start
|
||||||
override val endLabel: LabelNode
|
override val endLabel: LabelNode
|
||||||
get() = node.end
|
get() = node.end
|
||||||
}
|
|
||||||
|
|
||||||
public class TryCatchBlockNodeWrapper(val node: TryCatchBlockNode) : IntervalWithHandler {
|
override fun split(split: Interval, keepStart: Boolean): SplittedPair<LocalVarNodeWrapper> {
|
||||||
override val startLabel: LabelNode
|
val newPartInterval = if (keepStart) {
|
||||||
get() = node.start
|
val oldEnd = endLabel
|
||||||
override val endLabel: LabelNode
|
node.end = split.startLabel
|
||||||
get() = node.end
|
Pair(split.endLabel, oldEnd)
|
||||||
override val handler: LabelNode
|
}
|
||||||
get() = node.handler
|
else {
|
||||||
override val type: String?
|
val oldStart = startLabel
|
||||||
get() = node.type
|
node.start = split.endLabel
|
||||||
}
|
Pair(oldStart, split.startLabel)
|
||||||
|
}
|
||||||
|
|
||||||
|
return SplittedPair(this, LocalVarNodeWrapper(
|
||||||
|
LocalVariableNode(node.name, node.desc, node.signature, newPartInterval.first, newPartInterval.second, node.index)
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -659,17 +659,9 @@ public class InlineCodegen extends CallGenerator {
|
|||||||
//Exception table for external try/catch/finally blocks will be generated in original codegen after exiting this method
|
//Exception table for external try/catch/finally blocks will be generated in original codegen after exiting this method
|
||||||
InlineCodegenUtil.insertNodeBefore(finallyNode, intoNode, curInstr);
|
InlineCodegenUtil.insertNodeBefore(finallyNode, intoNode, curInstr);
|
||||||
|
|
||||||
List<TryCatchBlockNodeWrapper> blocks = processor.getCoveringFromInnermost();
|
List<TryCatchBlockNodeInfo> blocks = new ArrayList<TryCatchBlockNodeInfo>(processor.getTryBlocksMetaInfo().getCurrentIntervals());
|
||||||
ListIterator<TryCatchBlockNodeWrapper> iterator = blocks.listIterator(blocks.size());
|
for (TryCatchBlockNodeInfo block : blocks) {
|
||||||
while (iterator.hasPrevious()) {
|
processor.getTryBlocksMetaInfo().split(block, new SimpleInterval((LabelNode) start.info, (LabelNode) end.info), false);
|
||||||
TryCatchBlockNodeWrapper previous = iterator.previous();
|
|
||||||
LabelNode oldStart = previous.getStartLabel();
|
|
||||||
TryCatchBlockNode node = previous.getNode();
|
|
||||||
node.start = (LabelNode) end.info;
|
|
||||||
processor.remapStartLabel(oldStart, previous);
|
|
||||||
|
|
||||||
TryCatchBlockNode additionalNode = new TryCatchBlockNode(oldStart, (LabelNode) start.info, node.handler, node.type);
|
|
||||||
processor.addTryNode(additionalNode);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -677,15 +669,14 @@ public class InlineCodegen extends CallGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
processor.sortTryCatchBlocks();
|
processor.sortTryCatchBlocks();
|
||||||
Iterable<TryCatchBlockNodeWrapper> nodes = processor.getNonEmptyNodes();
|
Iterable<TryCatchBlockNodeInfo> nodes = processor.getNonEmptyNodes();
|
||||||
intoNode.tryCatchBlocks.clear();
|
intoNode.tryCatchBlocks.clear();
|
||||||
for (TryCatchBlockNodeWrapper node : nodes) {
|
for (TryCatchBlockNodeInfo node : nodes) {
|
||||||
intoNode.tryCatchBlocks.add(node.getNode());
|
intoNode.tryCatchBlocks.add(node.getNode());
|
||||||
}
|
}
|
||||||
|
|
||||||
intoNode.localVariables.clear();
|
intoNode.localVariables.clear();
|
||||||
List<LocalVarNodeWrapper> intervals = processor.getLocalVarsMetaInfo().getAllIntervals();
|
for (LocalVarNodeWrapper interval : processor.getLocalVarsMetaInfo().getAllIntervals()) {
|
||||||
for (LocalVarNodeWrapper interval : intervals) {
|
|
||||||
intoNode.localVariables.add(interval.getNode());
|
intoNode.localVariables.add(interval.getNode());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-27
@@ -81,8 +81,9 @@ public class InternalFinallyBlockInliner extends CoveringTryCatchNodeProcessor<T
|
|||||||
//due to code generation specific they placed before function TryCatchBlockNodes
|
//due to code generation specific they placed before function TryCatchBlockNodes
|
||||||
private InternalFinallyBlockInliner(@NotNull MethodNode inlineFun, List<TryCatchBlockNodeInfo> inlineFunTryBlockInfo) {
|
private InternalFinallyBlockInliner(@NotNull MethodNode inlineFun, List<TryCatchBlockNodeInfo> inlineFunTryBlockInfo) {
|
||||||
this.inlineFun = inlineFun;
|
this.inlineFun = inlineFun;
|
||||||
|
IntervalMetaInfo<TryCatchBlockNodeInfo> info = getTryBlocksMetaInfo();
|
||||||
for (TryCatchBlockNodeInfo block : inlineFunTryBlockInfo) {
|
for (TryCatchBlockNodeInfo block : inlineFunTryBlockInfo) {
|
||||||
addNewTryCatchNode(block);
|
info.addNewInterval(block);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -293,6 +294,7 @@ public class InternalFinallyBlockInliner extends CoveringTryCatchNodeProcessor<T
|
|||||||
List<TryBlockCluster<TryCatchBlockNodePosition>> clusters = InlinePackage.doClustering(tryCatchBlockPresentInFinally);
|
List<TryBlockCluster<TryCatchBlockNodePosition>> clusters = InlinePackage.doClustering(tryCatchBlockPresentInFinally);
|
||||||
Map<LabelNode, TryBlockCluster<TryCatchBlockNodePosition>> handler2Cluster = new HashMap<LabelNode, TryBlockCluster<TryCatchBlockNodePosition>>();
|
Map<LabelNode, TryBlockCluster<TryCatchBlockNodePosition>> handler2Cluster = new HashMap<LabelNode, TryBlockCluster<TryCatchBlockNodePosition>>();
|
||||||
|
|
||||||
|
IntervalMetaInfo<TryCatchBlockNodeInfo> tryBlocksMetaInfo = getTryBlocksMetaInfo();
|
||||||
for (TryBlockCluster<TryCatchBlockNodePosition> cluster : clusters) {
|
for (TryBlockCluster<TryCatchBlockNodePosition> cluster : clusters) {
|
||||||
List<TryCatchBlockNodePosition> clusterBlocks = cluster.getBlocks();
|
List<TryCatchBlockNodePosition> clusterBlocks = cluster.getBlocks();
|
||||||
TryCatchBlockNodePosition block0 = clusterBlocks.get(0);
|
TryCatchBlockNodePosition block0 = clusterBlocks.get(0);
|
||||||
@@ -313,8 +315,7 @@ public class InternalFinallyBlockInliner extends CoveringTryCatchNodeProcessor<T
|
|||||||
|
|
||||||
assert inlineFun.instructions.indexOf(additionalTryCatchBlock.start) <= inlineFun.instructions.indexOf(additionalTryCatchBlock.end);
|
assert inlineFun.instructions.indexOf(additionalTryCatchBlock.start) <= inlineFun.instructions.indexOf(additionalTryCatchBlock.end);
|
||||||
|
|
||||||
TryCatchBlockNodeInfo newInfo = new TryCatchBlockNodeInfo(additionalTryCatchBlock, true);
|
tryBlocksMetaInfo.addNewInterval(new TryCatchBlockNodeInfo(additionalTryCatchBlock, true));
|
||||||
addNewTryCatchNode(newInfo);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (clusterPosition == TryCatchPosition.END) {
|
else if (clusterPosition == TryCatchPosition.END) {
|
||||||
@@ -367,37 +368,16 @@ public class InternalFinallyBlockInliner extends CoveringTryCatchNodeProcessor<T
|
|||||||
// so we should split original interval by inserted finally one
|
// so we should split original interval by inserted finally one
|
||||||
for (TryCatchBlockNodeInfo block : toProcess) {
|
for (TryCatchBlockNodeInfo block : toProcess) {
|
||||||
//update exception mapping
|
//update exception mapping
|
||||||
LabelNode oldStartNode = block.getNode().start;
|
tryBlocksMetaInfo.split(block, new SimpleInterval((LabelNode) newFinallyStart.info, (LabelNode) newFinallyEnd.info), false);
|
||||||
block.getNode().start = (LabelNode) newFinallyEnd.info;
|
|
||||||
remapStartLabel(oldStartNode, block);
|
|
||||||
|
|
||||||
patched.add(block);
|
patched.add(block);
|
||||||
|
|
||||||
TryCatchBlockNode additionalTryCatchBlock =
|
|
||||||
new TryCatchBlockNode(oldStartNode, (LabelNode) newFinallyStart.info, block.getNode().handler, block.getNode().type);
|
|
||||||
|
|
||||||
TryCatchBlockNodeInfo newInfo = new TryCatchBlockNodeInfo(additionalTryCatchBlock, block.getOnlyCopyNotProcess());
|
|
||||||
addNewTryCatchNode(newInfo);
|
|
||||||
|
|
||||||
//TODO add assert
|
//TODO add assert
|
||||||
}
|
}
|
||||||
sortTryCatchBlocks();
|
sortTryCatchBlocks();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void patchTryBlocks(@NotNull LabelNode newStartLabelNode, @NotNull TryCatchBlockNodeInfo endNode) {
|
private void patchTryBlocks(@NotNull LabelNode newStartLabelNode, @NotNull TryCatchBlockNodeInfo endNode) {
|
||||||
LabelNode oldStart = endNode.getStartLabel();
|
getTryBlocksMetaInfo()
|
||||||
endNode.getNode().start = newStartLabelNode;
|
.split(endNode, new SimpleInterval((LabelNode) endNode.getNode().end.getLabel().info, newStartLabelNode), false);
|
||||||
remapStartLabel(oldStart, endNode);
|
|
||||||
|
|
||||||
TryCatchBlockNode endTryBlock = endNode.getNode();
|
|
||||||
TryCatchBlockNode additionalTryCatchBlock =
|
|
||||||
new TryCatchBlockNode(oldStart,
|
|
||||||
(LabelNode) endTryBlock.end.getLabel().info,
|
|
||||||
endTryBlock.handler,
|
|
||||||
endTryBlock.type);
|
|
||||||
|
|
||||||
TryCatchBlockNodeInfo newInfo = new TryCatchBlockNodeInfo(additionalTryCatchBlock, endNode.getOnlyCopyNotProcess());
|
|
||||||
addNewTryCatchNode(newInfo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static LabelNode getNewOrOldLabel(LabelNode oldHandler, @NotNull Set<LabelNode> labelsInsideFinally) {
|
private static LabelNode getNewOrOldLabel(LabelNode oldHandler, @NotNull Set<LabelNode> labelsInsideFinally) {
|
||||||
|
|||||||
@@ -26,15 +26,17 @@ enum class TryCatchPosition {
|
|||||||
INNER
|
INNER
|
||||||
}
|
}
|
||||||
|
|
||||||
public class SplittedPair(val patchedPart: SplittableInterval, val newPart: SplittableInterval)
|
public class SplittedPair<T: Interval>(val patchedPart: T, val newPart: T)
|
||||||
|
|
||||||
|
class SimpleInterval(override val startLabel: LabelNode, override val endLabel: LabelNode ) : Interval
|
||||||
|
|
||||||
trait Interval {
|
trait Interval {
|
||||||
val startLabel: LabelNode
|
val startLabel: LabelNode
|
||||||
val endLabel: LabelNode
|
val endLabel: LabelNode
|
||||||
}
|
}
|
||||||
|
|
||||||
trait SplittableInterval : Interval {
|
trait SplittableInterval<T: Interval> : Interval {
|
||||||
fun split(split: Interval, keepStart: Boolean): SplittedPair
|
fun split(split: Interval, keepStart: Boolean): SplittedPair<T>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -43,31 +45,35 @@ trait IntervalWithHandler : Interval {
|
|||||||
val type: String?
|
val type: String?
|
||||||
}
|
}
|
||||||
|
|
||||||
class TryCatchBlockNodeInfo(val node: TryCatchBlockNode, val onlyCopyNotProcess: Boolean) : IntervalWithHandler, SplittableInterval {
|
class TryCatchBlockNodeInfo(val node: TryCatchBlockNode, val onlyCopyNotProcess: Boolean) : IntervalWithHandler, SplittableInterval<TryCatchBlockNodeInfo> {
|
||||||
override val startLabel: LabelNode
|
override val startLabel: LabelNode
|
||||||
get() = node.start
|
get() = node.start
|
||||||
override val endLabel: LabelNode
|
override val endLabel: LabelNode
|
||||||
get() = node.end
|
get() = node.end
|
||||||
override val handler: LabelNode
|
override val handler: LabelNode
|
||||||
get() = node.handler
|
get() = node.handler
|
||||||
override val type: String?
|
override val type: String?
|
||||||
get() = node.type
|
get() = node.type
|
||||||
|
|
||||||
override fun split(split: Interval, keepStart: Boolean): SplittedPair {
|
override fun split(by: Interval, keepStart: Boolean): SplittedPair<TryCatchBlockNodeInfo> {
|
||||||
val newPart = if (keepStart) {
|
val newPartInterval = if (keepStart) {
|
||||||
val oldEnd = endLabel
|
val oldEnd = endLabel
|
||||||
node.end = split.startLabel
|
node.end = by.startLabel
|
||||||
TryCatchBlockNodeInfo(TryCatchBlockNode(split.endLabel, oldEnd, handler, type), onlyCopyNotProcess)
|
Pair(by.endLabel, oldEnd)
|
||||||
} else {
|
|
||||||
val oldStart = startLabel
|
|
||||||
node.start = split.endLabel
|
|
||||||
TryCatchBlockNodeInfo(TryCatchBlockNode(oldStart, split.startLabel, handler, type), onlyCopyNotProcess)
|
|
||||||
}
|
}
|
||||||
return SplittedPair(this, newPart)
|
else {
|
||||||
|
val oldStart = startLabel
|
||||||
|
node.start = by.endLabel
|
||||||
|
Pair(oldStart, by.startLabel)
|
||||||
|
}
|
||||||
|
return SplittedPair(
|
||||||
|
this,
|
||||||
|
TryCatchBlockNodeInfo(TryCatchBlockNode(newPartInterval.first, newPartInterval.second, handler, type), onlyCopyNotProcess)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TryCatchBlockNodePosition(val nodeInfo: TryCatchBlockNodeInfo, var position: TryCatchPosition): IntervalWithHandler by nodeInfo {
|
class TryCatchBlockNodePosition(val nodeInfo: TryCatchBlockNodeInfo, var position: TryCatchPosition) : IntervalWithHandler by nodeInfo {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,13 +83,13 @@ class TryBlockCluster<T : IntervalWithHandler>(val blocks: MutableList<T>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun <T: IntervalWithHandler> doClustering(blocks: List<T>) : List<TryBlockCluster<T>> {
|
fun <T : IntervalWithHandler> doClustering(blocks: List<T>): List<TryBlockCluster<T>> {
|
||||||
[data] class TryBlockInterval(val startLabel: LabelNode, val endLabel: LabelNode)
|
[data] class TryBlockInterval(val startLabel: LabelNode, val endLabel: LabelNode)
|
||||||
|
|
||||||
val clusters = linkedMapOf<TryBlockInterval, TryBlockCluster<T>>()
|
val clusters = linkedMapOf<TryBlockInterval, TryBlockCluster<T>>()
|
||||||
blocks.forEach { block ->
|
blocks.forEach { block ->
|
||||||
val interval = TryBlockInterval(firstLabelInChain(block.startLabel), firstLabelInChain(block.endLabel))
|
val interval = TryBlockInterval(firstLabelInChain(block.startLabel), firstLabelInChain(block.endLabel))
|
||||||
val cluster = clusters.getOrPut(interval, {TryBlockCluster(arrayListOf())})
|
val cluster = clusters.getOrPut(interval, { TryBlockCluster(arrayListOf()) })
|
||||||
cluster.blocks.add(block)
|
cluster.blocks.add(block)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user