AS3 parser: static method scope fix, final attr. fix, Classes resolving

This commit is contained in:
Jindra Pet��k
2014-04-14 08:36:42 +02:00
parent 47009e2748
commit 596854c379
11 changed files with 103 additions and 51 deletions
@@ -18,6 +18,7 @@ package com.jpexs.decompiler.flash;
import com.jpexs.decompiler.flash.abc.types.ABCException;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.flash.abc.types.ScriptInfo;
import com.jpexs.decompiler.graph.GraphTargetItem;
import java.io.Serializable;
import java.util.ArrayList;
@@ -47,6 +48,8 @@ public class SourceGeneratorLocalData implements Serializable {
public Map<MethodBody, List<Integer>> traitUsages = new HashMap<>();
public String pkg = "";
public List<GraphTargetItem> scopeStack = new ArrayList<GraphTargetItem>();
public boolean documentClass;
public ScriptInfo currentScript;
public SourceGeneratorLocalData(HashMap<String, Integer> registerVars, Integer inFunction, Boolean inMethod, Integer forInLevel) {
this.registerVars = registerVars;
@@ -116,7 +116,7 @@ public class CoerceAVM2Item extends AVM2Item {
ins = new AVM2Instruction(0, new CoerceSIns(), new int[]{}, new byte[0]);
break;
default:
int type_index = new TypeItem(type).resolveClass(((AVM2SourceGenerator) generator).abc);
int type_index = AVM2SourceGenerator.resolveType(new TypeItem(type),(((AVM2SourceGenerator) generator).abc));
ins = new AVM2Instruction(0, new CoerceIns(), new int[]{type_index}, new byte[0]);
break;
}
@@ -36,8 +36,10 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.LookupSwitchIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.GetLocal0Ins;
import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.KillIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.other.FindPropertyStrictIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.other.GetGlobalScopeIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.other.GetLexIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.other.GetScopeObjectIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.other.GetSlotIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.other.HasNext2Ins;
import com.jpexs.decompiler.flash.abc.avm2.instructions.other.InitPropertyIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.other.LabelIns;
@@ -1077,6 +1079,7 @@ public class AVM2SourceGenerator implements SourceGenerator {
Trait[] it = generateTraitsPhase1(pkg, name, superName, false, localData, traitItems, instanceInfo.instance_traits);
Trait[] st = generateTraitsPhase1(pkg, name, superName, true, localData, traitItems, classInfo.static_traits);
generateTraitsPhase2(pkg.packageName,traitItems, it, openedNamespaces, localData);
generateTraitsPhase2(pkg.packageName,traitItems, st, openedNamespaces, localData);
generateTraitsPhase3(initScope, pkg, name, superName, false, localData, traitItems, instanceInfo.instance_traits, it);
generateTraitsPhase3(initScope, pkg, name, superName, true, localData, traitItems, classInfo.static_traits, st);
if (constructor == null) {
@@ -1259,6 +1262,8 @@ public class AVM2SourceGenerator implements SourceGenerator {
newlocalData.pkg = localData.pkg;
newlocalData.callStack.addAll(localData.callStack);
newlocalData.traitUsages = localData.traitUsages;
newlocalData.currentScript = localData.currentScript;
newlocalData.documentClass = localData.documentClass;
localData = newlocalData;
localData.activationReg = 0;
@@ -1714,7 +1719,7 @@ public class AVM2SourceGenerator implements SourceGenerator {
if (mai.isStatic() != generateStatic) {
continue;
}
((TraitMethodGetterSetter) traits[k]).method_info = method(new ArrayList<MethodBody>(), pkg.packageName, mai.needsActivation, mai.subvariables, initScope + 1/*class scope*/, mai.hasRest, mai.line, className, superName, false, localData, mai.paramTypes, mai.paramNames, mai.paramValues, mai.body, mai.retType);
((TraitMethodGetterSetter) traits[k]).method_info = method(new ArrayList<MethodBody>(), pkg.packageName, mai.needsActivation, mai.subvariables, initScope + (mai.isStatic()?0:1), mai.hasRest, mai.line, className, superName, false, localData, mai.paramTypes, mai.paramNames, mai.paramValues, mai.body, mai.retType);
} else if (item instanceof FunctionAVM2Item) {
FunctionAVM2Item fai = (FunctionAVM2Item) item;
((TraitFunction) traits[k]).method_info = method(new ArrayList<MethodBody>(), pkg.packageName, fai.needsActivation, fai.subvariables, initScope, fai.hasRest, fai.line, className, superName, false, localData, fai.paramTypes, fai.paramNames, fai.paramValues, fai.body, fai.retType);
@@ -1823,7 +1828,7 @@ public class AVM2SourceGenerator implements SourceGenerator {
tmgs.kindType = (item instanceof MethodAVM2Item) ? Trait.TRAIT_METHOD : ((item instanceof GetterAVM2Item) ? Trait.TRAIT_GETTER : Trait.TRAIT_SETTER);
//tmgs.name_index = traitName(((MethodAVM2Item) item).namespace, ((MethodAVM2Item) item).functionName);
tmgs.disp_id = 0; //0 = disable override optimization; TODO: handle this
if (mai.isFinal()) {
if (mai.isFinal()||mai.isStatic()) {
tmgs.kindFlags |= Trait.ATTR_Final;
}
if (mai.isOverride()) {
@@ -1845,8 +1850,9 @@ public class AVM2SourceGenerator implements SourceGenerator {
return traits;
}
public ScriptInfo generateScriptInfo(PackageAVM2Item pkg, SourceGeneratorLocalData localData, List<GraphTargetItem> commands, boolean documentClass) throws ParseException, CompilationException {
public ScriptInfo generateScriptInfo(PackageAVM2Item pkg, SourceGeneratorLocalData localData, List<GraphTargetItem> commands) throws ParseException, CompilationException {
ScriptInfo si = new ScriptInfo();
localData.currentScript = si;
Trait[] traitArr = generateTraitsPhase1(pkg, null, null, false, localData, commands, si.traits);
generateTraitsPhase2(pkg.packageName,commands, traitArr, new ArrayList<Integer>(), localData);
MethodInfo mi = new MethodInfo(new int[0], 0, 0, 0, new ValueKind[0], new int[0]);
@@ -1855,6 +1861,7 @@ public class AVM2SourceGenerator implements SourceGenerator {
mb.code = new AVM2Code();
mb.code.code.add(ins(new GetLocal0Ins()));
mb.code.code.add(ins(new PushScopeIns()));
int traitScope = 1;
@@ -1863,7 +1870,7 @@ public class AVM2SourceGenerator implements SourceGenerator {
TraitClass tc = (TraitClass) t;
List<Integer> parents = new ArrayList<>();
parentNamesAddNames(abc, allABCs, abc.instance_info.get(tc.class_info).name_index, parents, new ArrayList<String>(), new ArrayList<String>());
if (documentClass) {
if (localData.documentClass) {
mb.code.code.add(ins(new GetScopeObjectIns(), 0));
traitScope++;
} else {
@@ -1885,7 +1892,7 @@ public class AVM2SourceGenerator implements SourceGenerator {
}
mb.code.code.add(ins(new ReturnVoidIns()));
mb.autoFillStats(abc, documentClass ? 1 : 0);
mb.autoFillStats(abc, localData.documentClass ? 1 : 0);
abc.addMethodBody(mb);
si.init_index = mb.method_info;
localData.pkg = pkg.packageName;
@@ -2067,4 +2074,66 @@ public class AVM2SourceGenerator implements SourceGenerator {
}
return 0;
}
@Override
public List<GraphSourceItem> generate(SourceGeneratorLocalData localData, TypeItem item) throws CompilationException {
String currentFullClassName = localData.currentClass==null?null:(localData.pkg.equals("")?localData.currentClass:localData.pkg+"."+localData.currentClass);
if(localData.documentClass && item.toString().equals(currentFullClassName)){
int slotId = 0;
int c = abc.findClassByName(currentFullClassName);
for(Trait t:localData.currentScript.traits.traits){
if(t instanceof TraitClass){
TraitClass tc=(TraitClass)t;
if(tc.class_info == c){
slotId = tc.slot_id;
break;
}
}
}
return GraphTargetItem.toSourceMerge(localData, this, ins(new GetGlobalScopeIns()),ins(new GetSlotIns(),slotId));
}else{
return GraphTargetItem.toSourceMerge(localData, this, ins(new GetLexIns(),resolveType(item, abc)));
}
}
public static int resolveType(TypeItem type,ABC abc) {
String name = type.fullTypeName;
String pkg = "";
int name_index = 0;
if (name.contains(".")) {
pkg = name.substring(0, name.lastIndexOf('.'));
name = name.substring(name.lastIndexOf('.') + 1);
}
for (InstanceInfo ii : abc.instance_info) {
Multiname mname = abc.constants.constant_multiname.get(ii.name_index);
if (mname.getName(abc.constants, new ArrayList<String>()).equals(name)) {
if (mname.getNamespace(abc.constants).hasName(pkg, abc.constants)) {
name_index = ii.name_index;
break;
}
}
}
for (int i = 1; i < abc.constants.constant_multiname.size(); i++) {
Multiname mname = abc.constants.constant_multiname.get(i);
if (name.equals(mname.getName(abc.constants, new ArrayList<String>()))) {
if (pkg.equals(mname.getNamespace(abc.constants).getName(abc.constants))) {
name_index = i;
break;
}
}
}
if(name_index == 0){
name_index = abc.constants.getMultinameId(new Multiname(Multiname.QNAME, abc.constants.getStringId(name, true), abc.constants.getNamespaceId(new Namespace(Namespace.KIND_PACKAGE, abc.constants.getStringId(pkg, true)), 0, true), 0, 0, new ArrayList<Integer>()), true);
}
if(type.subtypes.isEmpty()){
return name_index;
}
List<Integer> params=new ArrayList<>();
for(String s:type.subtypes){
params.add(resolveType(new TypeItem(s),abc));
}
return abc.constants.getMultinameId(new Multiname(Multiname.TYPENAME,0,0,0,name_index,params),true);
}
}
@@ -683,7 +683,7 @@ public class ActionScriptParser {
List<Integer> indices = new ArrayList<>();
List<String> names = new ArrayList<>();
List<String> namespaces = new ArrayList<>();
AVM2SourceGenerator.parentNamesAddNames(abc, otherABCs, ((TypeItem) ((UnresolvedAVM2Item) extendsStr).resolve(new ArrayList<GraphTargetItem>(), new ArrayList<String>(), abc, otherABCs, new ArrayList<MethodBody>(), new ArrayList<AssignableAVM2Item>())).resolveClass(abc), indices, names, namespaces);
AVM2SourceGenerator.parentNamesAddNames(abc, otherABCs, AVM2SourceGenerator.resolveType(((TypeItem) ((UnresolvedAVM2Item) extendsStr).resolve(new ArrayList<GraphTargetItem>(), new ArrayList<String>(), abc, otherABCs, new ArrayList<MethodBody>(), new ArrayList<AssignableAVM2Item>())),abc), indices, names, namespaces);
for (int i = 0; i < names.size(); i++) {
if (namespaces.get(i).isEmpty()) {
continue;
@@ -1806,7 +1806,8 @@ public class ActionScriptParser {
className = ((ClassAVM2Item) it).className;
}
}
abc.script_info.add(gen.generateScriptInfo(pkg, localData, pkg.items, documentClass));
localData.documentClass = documentClass;
abc.script_info.add(gen.generateScriptInfo(pkg, localData, pkg.items));
}
public void addScript(String s, boolean documentClass, String fileName) throws ParseException, IOException, CompilationException {
@@ -70,7 +70,6 @@ public class ConstructSomethingAVM2Item extends CallAVM2Item {
if (resname instanceof UnresolvedAVM2Item) {
resname = ((UnresolvedAVM2Item) resname).resolved;
}
if (resname instanceof TypeItem) {
TypeItem prop = (TypeItem) resname;
if(!prop.subtypes.isEmpty()){ //It's Vector - TypeName
@@ -221,12 +221,12 @@ public class NameAVM2Item extends AssignableAVM2Item {
ins = ins(new CoerceSIns());
break;
default:
int type_index = type.resolveClass(((AVM2SourceGenerator) generator).abc);
int type_index = AVM2SourceGenerator.resolveType(type,((AVM2SourceGenerator) generator).abc);
ins = ins(new CoerceIns(), type_index);
break;
}
} else {
int type_index = type.resolveClass(((AVM2SourceGenerator) generator).abc);
int type_index = AVM2SourceGenerator.resolveType(type,((AVM2SourceGenerator) generator).abc);
ins = ins(new CoerceIns(), type_index);
}
}
@@ -216,7 +216,7 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item {
ins = ins(new CoerceSIns());
break;
default:
int type_index = new TypeItem(type).resolveClass(((AVM2SourceGenerator) generator).abc);
int type_index = AVM2SourceGenerator.resolveType(new TypeItem(type),((AVM2SourceGenerator) generator).abc);
ins = ins(new CoerceIns(), type_index);
break;
}
@@ -1,4 +1,5 @@
TODO List for AS3 parser/compiler:
------------------------------
- E4X (XML)
- default xml namespace
- default xml namespace
- calculation of dispid(method override, static methods)
@@ -49,6 +49,7 @@ 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.TypeItem;
import com.jpexs.decompiler.graph.model.AndItem;
import com.jpexs.decompiler.graph.model.BreakItem;
import com.jpexs.decompiler.graph.model.CommaExpressionItem;
@@ -763,4 +764,12 @@ public class ActionSourceGenerator implements SourceGenerator {
ret.addAll(lastExpr.toSource(localData, this));
return ret;
}
@Override
public List<GraphSourceItem> generate(SourceGeneratorLocalData localData, TypeItem item) throws CompilationException {
//Unsupported in AS1/2
return new ArrayList<>();
}
}
@@ -65,4 +65,6 @@ public interface SourceGenerator {
public List<GraphSourceItem> generate(SourceGeneratorLocalData localData, List<GraphTargetItem> commands) throws CompilationException;
public List<GraphSourceItem> generate(SourceGeneratorLocalData localData, CommaExpressionItem item) throws CompilationException;
public List<GraphSourceItem> generate(SourceGeneratorLocalData localData, TypeItem item) throws CompilationException;
}
@@ -16,6 +16,7 @@
*/
package com.jpexs.decompiler.graph;
import com.jpexs.decompiler.flash.SourceGeneratorLocalData;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.types.InstanceInfo;
import com.jpexs.decompiler.flash.abc.types.Multiname;
@@ -102,43 +103,10 @@ public class TypeItem extends GraphTargetItem {
}
public int resolveClass(ABC abc) {
String name = fullTypeName;
String pkg = "";
int name_index = 0;
if (name.contains(".")) {
pkg = name.substring(0, name.lastIndexOf('.'));
name = name.substring(name.lastIndexOf('.') + 1);
}
for (InstanceInfo ii : abc.instance_info) {
Multiname mname = abc.constants.constant_multiname.get(ii.name_index);
if (mname.getName(abc.constants, new ArrayList<String>()).equals(name)) {
if (mname.getNamespace(abc.constants).hasName(pkg, abc.constants)) {
name_index = ii.name_index;
break;
}
}
}
for (int i = 1; i < abc.constants.constant_multiname.size(); i++) {
Multiname mname = abc.constants.constant_multiname.get(i);
if (name.equals(mname.getName(abc.constants, new ArrayList<String>()))) {
if (pkg.equals(mname.getNamespace(abc.constants).getName(abc.constants))) {
name_index = i;
break;
}
}
}
if(name_index == 0){
name_index = abc.constants.getMultinameId(new Multiname(Multiname.QNAME, abc.constants.getStringId(name, true), abc.constants.getNamespaceId(new Namespace(Namespace.KIND_PACKAGE, abc.constants.getStringId(pkg, true)), 0, true), 0, 0, new ArrayList<Integer>()), true);
}
if(subtypes.isEmpty()){
return name_index;
}
List<Integer> params=new ArrayList<>();
for(String s:subtypes){
params.add(new TypeItem(s).resolveClass(abc));
}
return abc.constants.getMultinameId(new Multiname(Multiname.TYPENAME,0,0,0,name_index,params),true);
}
@Override
public List<GraphSourceItem> toSource(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException {
return generator.generate(localData, this);
}
}