/*
* Copyright (C) 2010-2016 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
package com.jpexs.decompiler.flash.abc.avm2.parser.script;
import com.jpexs.decompiler.flash.SourceGeneratorLocalData;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instructions;
import com.jpexs.decompiler.flash.abc.avm2.model.AVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.CoerceAVM2Item;
import com.jpexs.decompiler.graph.CompilationException;
import com.jpexs.decompiler.graph.GraphSourceItem;
import com.jpexs.decompiler.graph.GraphTargetItem;
import com.jpexs.decompiler.graph.SourceGenerator;
import com.jpexs.decompiler.graph.model.OrItem;
import java.util.ArrayList;
import java.util.List;
/**
*
* @author JPEXS
*/
public abstract class AssignableAVM2Item extends AVM2Item {
protected GraphTargetItem assignedValue;
protected GraphTargetItem makeCoerced(GraphTargetItem assignedValue, GraphTargetItem targetType) {
if (assignedValue instanceof OrItem) {
OrItem oi = (OrItem) assignedValue;
return new OrItem(assignedValue.getSrc(), assignedValue.getLineStartItem(), makeCoerced(oi.leftSide, targetType), makeCoerced(oi.rightSide, targetType));
}
//TODO: Is it needed for AndItem too?
return new CoerceAVM2Item(null, null, assignedValue, targetType);
}
public AssignableAVM2Item() {
this(null);
}
public abstract AssignableAVM2Item copy();
public AssignableAVM2Item(GraphTargetItem storeValue) {
super(null, null, PRECEDENCE_PRIMARY);
this.assignedValue = storeValue;
}
public abstract List<GraphSourceItem> toSourceChange(SourceGeneratorLocalData localData, SourceGenerator generator, boolean post, boolean decrement, boolean needsReturn) throws CompilationException;
public GraphTargetItem getAssignedValue() {
return assignedValue;
}
public void setAssignedValue(GraphTargetItem storeValue) {
this.assignedValue = storeValue;
}
public static List<GraphSourceItem> dupSetTemp(SourceGeneratorLocalData localData, SourceGenerator generator, Reference<Integer> register) {
register.setVal(getFreeRegister(localData, generator));
List<GraphSourceItem> ret = new ArrayList<>();
ret.add(ins(AVM2Instructions.Dup));
ret.add(generateSetLoc(register.getVal()));
return ret;
}
public static List<GraphSourceItem> setTemp(SourceGeneratorLocalData localData, SourceGenerator generator, Reference<Integer> register) {
register.setVal(getFreeRegister(localData, generator));
List<GraphSourceItem> ret = new ArrayList<>();
ret.add(generateSetLoc(register.getVal()));
return ret;
}
public static List<GraphSourceItem> getTemp(SourceGeneratorLocalData localData, SourceGenerator generator, Reference<Integer> register) {
if (register.getVal() < 0) {
return new ArrayList<>();
}
List<GraphSourceItem> ret = new ArrayList<>();
ret.add(generateGetLoc(register.getVal()));
return ret;
}
/*protected List<GraphSourceItem> getAndKillTemp(SourceGeneratorLocalData localData, SourceGenerator generator, Reference<Integer> register) {
killRegister(localData, generator, register.getVal());
List<GraphSourceItem> ret = new ArrayList<>();
ret.add(generateGetLoc(register.getVal()));
ret.add(ins(AVM2Instructions.Kill, register.getVal()));
return ret;
}*/
public static List<GraphSourceItem> killTemp(SourceGeneratorLocalData localData, SourceGenerator generator, List<Reference<Integer>> registers) {
List<GraphSourceItem> ret = new ArrayList<>();
for (Reference<Integer> register : registers) {
if (register.getVal() < 0) {
continue;
}
killRegister(localData, generator, register.getVal());
ret.add(ins(AVM2Instructions.Kill, register.getVal()));
}
return ret;
}
public static AVM2Instruction generateSetLoc(int regNumber) {
switch (regNumber) {
case -1:
return null;
case 0:
return ins(AVM2Instructions.SetLocal0);
case 1:
return ins(AVM2Instructions.SetLocal1);
case 2:
return ins(AVM2Instructions.SetLocal2);
case 3:
return ins(AVM2Instructions.SetLocal3);
default:
return ins(AVM2Instructions.SetLocal, regNumber);
}
}
public static AVM2Instruction generateGetLoc(int regNumber) {
switch (regNumber) {
case -1:
return null;
case 0:
return ins(AVM2Instructions.GetLocal0);
case 1:
return ins(AVM2Instructions.GetLocal1);
case 2:
return ins(AVM2Instructions.GetLocal2);
case 3:
return ins(AVM2Instructions.GetLocal3);
default:
return ins(AVM2Instructions.GetLocal, regNumber);
}
}
public static List<GraphSourceItem> generateGetSlot(int slotScope, int slotNumber) {
if (slotNumber == -1) {
return null;
}
List<GraphSourceItem> ret = new ArrayList<>();
ret.add(ins(AVM2Instructions.GetScopeObject, slotScope));
ret.add(ins(AVM2Instructions.GetSlot, slotNumber));
return ret;
}
public static List<GraphSourceItem> generateSetSlot(SourceGeneratorLocalData localData, SourceGenerator generator, GraphTargetItem val, int slotScope, int slotNumber) throws CompilationException {
if (slotNumber == -1) {
return null;
}
List<GraphSourceItem> ret = new ArrayList<>();
ret.add(ins(AVM2Instructions.GetScopeObject, slotScope));
ret.addAll(val.toSource(localData, generator));
ret.add(ins(AVM2Instructions.SetSlot, slotNumber));
return ret;
}
}