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    
017    package org.jetbrains.jet.lang.cfg.pseudocode;
018    
019    import com.google.common.collect.Sets;
020    import org.jetbrains.annotations.NotNull;
021    import org.jetbrains.annotations.Nullable;
022    
023    import java.util.Collection;
024    import java.util.LinkedHashSet;
025    
026    public abstract class InstructionImpl implements Instruction {
027        private Pseudocode owner;
028        private final Collection<Instruction> previousInstructions = new LinkedHashSet<Instruction>();
029        private final Collection<Instruction> copies = Sets.newHashSet();
030        @NotNull
031        protected final LexicalScope lexicalScope;
032        private Instruction original;
033        protected boolean isDead = false;
034    
035        protected InstructionImpl(@NotNull LexicalScope lexicalScope) {
036            this.lexicalScope = lexicalScope;
037        }
038    
039        @Override
040        @NotNull
041        public Pseudocode getOwner() {
042            return owner;
043        }
044    
045        @Override
046        public void setOwner(@NotNull Pseudocode owner) {
047            assert this.owner == null || this.owner == owner;
048            this.owner = owner;
049        }
050    
051        @NotNull
052        @Override
053        public Collection<Instruction> getPreviousInstructions() {
054            return previousInstructions;
055        }
056    
057        @Nullable
058        protected Instruction outgoingEdgeTo(@Nullable Instruction target) {
059            if (target != null) {
060                target.getPreviousInstructions().add(this);
061            }
062            return target;
063        }
064    
065        public void die() {
066            isDead = true;
067        }
068        
069        public boolean isDead() {
070            return isDead;
071        }
072    
073        public final Instruction copy() {
074            return updateCopyInfo(createCopy());
075        }
076    
077        @NotNull
078        protected abstract Instruction createCopy();
079    
080        @NotNull
081        @Override
082        public Collection<Instruction> getCopies() {
083            if (original != null) {
084                Collection<Instruction> originalCopies = Sets.newHashSet(original.getCopies());
085                originalCopies.remove(this);
086                originalCopies.add(original);
087                return originalCopies;
088            }
089            return copies;
090        }
091    
092        private void addCopy(@NotNull Instruction instruction) {
093            copies.add(instruction);
094        }
095    
096        private void setOriginal(@NotNull Instruction original) {
097            assert this.original == null :
098                    "Instruction can't have two originals: this.original = " + this.original + "; new original = " + original;
099            this.original = original;
100        }
101    
102        @NotNull
103        @Override
104        public LexicalScope getLexicalScope() {
105            return lexicalScope;
106        }
107    
108        protected Instruction updateCopyInfo(@NotNull Instruction instruction) {
109            addCopy(instruction);
110            ((InstructionImpl)instruction).setOriginal(this);
111            return instruction;
112        }
113    }