001/*
002 * Copyright 2010-2013 JetBrains s.r.o.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.jetbrains.jet.lang.cfg.pseudocode;
018
019import com.google.common.collect.Lists;
020import com.google.common.collect.Maps;
021import org.jetbrains.annotations.NotNull;
022import org.jetbrains.jet.lang.cfg.Label;
023
024import java.util.*;
025
026public class NondeterministicJumpInstruction extends InstructionImpl{
027    private Instruction next;
028    private final List<Label> targetLabels;
029    private final Map<Label, Instruction> resolvedTargets;
030
031    public NondeterministicJumpInstruction(List<Label> targetLabels) {
032        this.targetLabels = Lists.newArrayList(targetLabels);
033        resolvedTargets = Maps.newLinkedHashMap();
034    }
035
036    public NondeterministicJumpInstruction(Label targetLabel) {
037        this(Lists.newArrayList(targetLabel));
038    }
039
040    public List<Label> getTargetLabels() {
041        return targetLabels;
042    }
043
044    public Map<Label, Instruction> getResolvedTargets() {
045        return resolvedTargets;
046    }
047
048    public void setResolvedTarget(Label label, Instruction resolvedTarget) {
049        Instruction target = outgoingEdgeTo(resolvedTarget);
050        resolvedTargets.put(label, target);
051    }
052
053    public Instruction getNext() {
054        return next;
055    }
056    public void setNext(Instruction next) {
057        this.next = outgoingEdgeTo(next);
058    }
059
060    @Override
061    public void accept(InstructionVisitor visitor) {
062        visitor.visitNondeterministicJump(this);
063    }
064
065    @NotNull
066    @Override
067    public Collection<Instruction> getNextInstructions() {
068        List<Instruction> targetInstructions = Lists.newArrayList(getResolvedTargets().values());
069        targetInstructions.add(getNext());
070        return targetInstructions;
071    }
072
073    @Override
074    public String toString() {
075        StringBuilder sb = new StringBuilder();
076        sb.append("jmp?(");
077        for (Iterator<Label> iterator = targetLabels.iterator(); iterator.hasNext(); ) {
078            Label targetLabel = iterator.next();
079            sb.append(targetLabel.getName());
080            if (iterator.hasNext()) {
081                sb.append(", ");
082            }
083        }
084        sb.append(")");
085        return sb.toString();
086    }
087
088    @Override
089    protected Instruction createCopy() {
090        return createCopy(getTargetLabels());
091    }
092
093    @NotNull
094    public final Instruction copy(@NotNull List<Label> newTargetLabels) {
095        return updateCopyInfo(createCopy(newTargetLabels));
096    }
097
098    private Instruction createCopy(@NotNull List<Label> newTargetLabels) {
099        return new NondeterministicJumpInstruction(newTargetLabels);
100    }
101}