AS3 parser: with statement, try..catch scope fix

This commit is contained in:
Jindra Petk
2014-04-13 11:29:36 +02:00
parent 90025e1bf6
commit a435c21774
9 changed files with 343 additions and 166 deletions

View File

@@ -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.graph.GraphTargetItem;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
@@ -45,6 +46,7 @@ public class SourceGeneratorLocalData implements Serializable {
public List<MethodBody> callStack = new ArrayList<>();
public Map<MethodBody, List<Integer>> traitUsages = new HashMap<>();
public String pkg = "";
public List<GraphTargetItem> scopeStack = new ArrayList<GraphTargetItem>();
public SourceGeneratorLocalData(HashMap<String, Integer> registerVars, Integer inFunction, Boolean inMethod, Integer forInLevel) {
this.registerVars = registerVars;

View File

@@ -16,9 +16,15 @@
*/
package com.jpexs.decompiler.flash.abc.avm2.model;
import com.jpexs.decompiler.flash.SourceGeneratorLocalData;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.parser.script.AVM2SourceGenerator;
import com.jpexs.decompiler.flash.abc.avm2.parser.script.AssignableAVM2Item;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
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.LocalData;
import java.util.ArrayList;
@@ -28,6 +34,7 @@ public class WithAVM2Item extends AVM2Item {
public GraphTargetItem scope;
public List<GraphTargetItem> items;
public List<AssignableAVM2Item> subvariables = new ArrayList<AssignableAVM2Item>();
public WithAVM2Item(AVM2Instruction instruction, GraphTargetItem scope, List<GraphTargetItem> items) {
super(instruction, NOPRECEDENCE);
@@ -73,4 +80,10 @@ public class WithAVM2Item extends AVM2Item {
public boolean hasReturnValue() {
return false;
}
@Override
public List<GraphSourceItem> toSource(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException {
return ((AVM2SourceGenerator) generator).generate(localData, this);
}
}

View File

@@ -16,11 +16,16 @@
*/
package com.jpexs.decompiler.flash.abc.avm2.model;
import com.jpexs.decompiler.flash.SourceGeneratorLocalData;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
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.LocalData;
import java.util.List;
public class WithObjectAVM2Item extends AVM2Item {
@@ -45,4 +50,10 @@ public class WithObjectAVM2Item extends AVM2Item {
public boolean hasReturnValue() {
return false;
}
@Override
public List<GraphSourceItem> toSource(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException {
return scope.toSource(localData, generator);
}
}

View File

@@ -19,6 +19,7 @@ package com.jpexs.decompiler.flash.abc.avm2.model.clauses;
import com.jpexs.decompiler.flash.SourceGeneratorLocalData;
import com.jpexs.decompiler.flash.abc.avm2.model.AVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.parser.script.AVM2SourceGenerator;
import com.jpexs.decompiler.flash.abc.avm2.parser.script.AssignableAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.parser.script.NameAVM2Item;
import com.jpexs.decompiler.flash.abc.types.ABCException;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
@@ -40,6 +41,7 @@ public class TryAVM2Item extends AVM2Item implements Block {
public List<NameAVM2Item> catchExceptions2;
public List<List<GraphTargetItem>> catchCommands;
public List<GraphTargetItem> finallyCommands;
public List<List<AssignableAVM2Item>> catchVariables = new ArrayList<List<AssignableAVM2Item>>();
@Override
public List<List<GraphTargetItem>> getSubs() {

View File

@@ -52,18 +52,22 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PopScopeIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushByteIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushScopeIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushUndefinedIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushWithIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.SwapIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.types.CoerceAIns;
import com.jpexs.decompiler.flash.abc.avm2.model.AVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.BooleanAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.FloatValueAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.IntegerValueAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.LocalRegAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.NullAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.ReturnValueAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.ReturnVoidAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.StringAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.ThrowAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.UndefinedAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.WithAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.WithObjectAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.clauses.ForEachInAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.clauses.ForInAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.clauses.TryAVM2Item;
@@ -432,6 +436,21 @@ public class AVM2SourceGenerator implements SourceGenerator {
return ret;
}
public List<GraphSourceItem> generate(SourceGeneratorLocalData localData, WithAVM2Item item) throws CompilationException {
List<GraphSourceItem> ret = new ArrayList<>();
ret.addAll(item.scope.toSource(localData, this));
Reference<Integer> tempReg = new Reference<>(0);
ret.addAll(AssignableAVM2Item.dupSetTemp(localData, this, tempReg));
localData.scopeStack.add(new WithObjectAVM2Item(null, new LocalRegAVM2Item(null, tempReg.getVal(), null)));
ret.add(ins(new PushWithIns()));
ret.addAll(generate(localData, item.items));
ret.add(ins(new PopScopeIns()));
ret.addAll(AssignableAVM2Item.killTemp(localData, this, Arrays.asList(tempReg)));
localData.scopeStack.remove(localData.scopeStack.size() - 1);
return ret;
}
@Override
public List<GraphSourceItem> generate(SourceGeneratorLocalData localData, ForItem item) throws CompilationException {
List<GraphSourceItem> ret = new ArrayList<>();
@@ -585,7 +604,6 @@ public class AVM2SourceGenerator implements SourceGenerator {
List<GraphSourceItem> ret = new ArrayList<>();
boolean newFinallyReg = false;
int firstId = 0;
List<ABCException> newex = new ArrayList<>();
int aloneFinallyEx = -1;
int finallyEx = -1;
@@ -621,20 +639,80 @@ public class AVM2SourceGenerator implements SourceGenerator {
localData.finallyCatches.add(finId);
}
List<AVM2Instruction> tryCmds = generateToInsList(localData, item.tryCommands);
//int i = firstId + item.catchCommands.size() - 1;
List<AVM2Instruction> catches = new ArrayList<>();
Reference<Integer> tempReg = new Reference<>(0);
List<Integer> currentExceptionIds = new ArrayList<>();
List<List<AVM2Instruction>> catchCmds = new ArrayList<>();
for (int c = 0; c < item.catchCommands.size(); c++) {
catchCmds.add(generateToInsList(localData, item.catchCommands.get(c)));
int i = localData.exceptions.size();
localData.exceptions.add(newex.get(c));
currentExceptionIds.add(i);
//Reference<Integer> tempReg=new Reference<>(0);
List<AVM2Instruction> catchCmd = new ArrayList<>();
catchCmd.add(ins(new NewCatchIns(), i));
catchCmd.addAll(toInsList(AssignableAVM2Item.dupSetTemp(localData, this, tempReg)));
catchCmd.add(ins(new DupIns()));
catchCmd.add(ins(new PushScopeIns()));
catchCmd.add(ins(new SwapIns()));
catchCmd.add(ins(new SetSlotIns(), 1));
for (AssignableAVM2Item a : item.catchVariables.get(c)) {
GraphTargetItem r = a;
if (r instanceof UnresolvedAVM2Item) {
r = ((UnresolvedAVM2Item) r).resolved;
}
if (r instanceof NameAVM2Item) {
NameAVM2Item n = (NameAVM2Item) r;
if (item.catchExceptions2.get(c).getVariableName().equals(n.getVariableName())) {
n.setSlotScope(localData.scopeStack.size());
}
}
}
localData.scopeStack.add(new LocalRegAVM2Item(null, tempReg.getVal(), null));
catchCmd.addAll(generateToInsList(localData, item.catchCommands.get(c)));
localData.scopeStack.remove(localData.scopeStack.size() - 1);
catchCmd.add(ins(new PopScopeIns()));
catchCmd.addAll(toInsList(AssignableAVM2Item.killTemp(localData, this, Arrays.asList(tempReg))));
catchCmds.add(catchCmd);
}
for (int c = item.catchCommands.size() - 1; c >= 0; c--) {
List<AVM2Instruction> preCatches = new ArrayList<>();
/*preCatches.add(ins(new GetLocal0Ins()));
preCatches.add(ins(new PushScopeIns()));
preCatches.add(AssignableAVM2Item.generateGetLoc(localData.activationReg));
preCatches.add(ins(new PushScopeIns()));*/
for (GraphTargetItem s : localData.scopeStack) {
preCatches.addAll(toInsList(s.toSource(localData, this)));
if (s instanceof WithObjectAVM2Item) {
preCatches.add(ins(new PushWithIns()));
} else {
preCatches.add(ins(new PushScopeIns()));
}
}
//catchCmds.add(catchCmd);
preCatches.addAll(catchCmds.get(c));
catches.addAll(0, preCatches);
catches.add(0, new ExceptionMarkAVM2Instruction(currentExceptionIds.get(c), MARK_E_TARGET));
catches.add(0, ins(new JumpIns(), insToBytes(catches).length));
}
firstId = localData.exceptions.size();
if (aloneFinallyEx > -1) {
aloneFinallyEx += firstId;
localData.exceptions.add(newex.get(aloneFinallyEx));
aloneFinallyEx = localData.exceptions.size() - 1;
}
if (finallyEx > -1) {
finallyEx += firstId;
localData.exceptions.add(newex.get(finallyEx));
finallyEx = localData.exceptions.size() - 1;
}
for (int i = firstId; i < firstId + item.catchExceptions2.size(); i++) {
for (int i : currentExceptionIds) {
ret.add(new ExceptionMarkAVM2Instruction(i, MARK_E_START));
}
if (aloneFinallyEx > -1) {
@@ -646,43 +724,23 @@ public class AVM2SourceGenerator implements SourceGenerator {
ret.addAll(tryCmds);
for (int i = firstId; i < firstId + item.catchExceptions2.size(); i++) {
for (int i : currentExceptionIds) {
ret.add(new ExceptionMarkAVM2Instruction(i, MARK_E_END));
}
if (aloneFinallyEx > -1) {
ret.add(new ExceptionMarkAVM2Instruction(aloneFinallyEx, MARK_E_END));
}
int i = firstId + item.catchCommands.size() - 1;
List<AVM2Instruction> catches = new ArrayList<>();
Reference<Integer> tempReg = new Reference<>(0);
for (int c = item.catchCommands.size() - 1; c >= 0; c--) {
List<AVM2Instruction> preCatches = new ArrayList<>();
preCatches.add(ins(new GetLocal0Ins()));
preCatches.add(ins(new PushScopeIns()));
preCatches.add(AssignableAVM2Item.generateGetLoc(localData.activationReg));
preCatches.add(ins(new PushScopeIns()));
preCatches.add(ins(new NewCatchIns(), i));
preCatches.addAll(toInsList(AssignableAVM2Item.dupSetTemp(localData, this, tempReg)));
preCatches.add(ins(new DupIns()));
preCatches.add(ins(new PushScopeIns()));
preCatches.add(ins(new SwapIns()));
preCatches.add(ins(new SetSlotIns(), 1));
preCatches.addAll(catchCmds.get(c));
preCatches.add(ins(new PopScopeIns()));
preCatches.addAll(toInsList(AssignableAVM2Item.killTemp(localData, this, Arrays.asList(tempReg))));
catches.addAll(0, preCatches);
catches.add(0, new ExceptionMarkAVM2Instruction(i, MARK_E_TARGET));
i--;
catches.add(0, ins(new JumpIns(), insToBytes(catches).length));
}
if (aloneFinallyEx > -1) {
List<AVM2Instruction> preCatches = new ArrayList<>();
preCatches.add(ins(new GetLocal0Ins()));
preCatches.add(ins(new PushScopeIns()));
preCatches.add(AssignableAVM2Item.generateGetLoc(localData.activationReg));
preCatches.add(ins(new PushScopeIns()));
for (GraphTargetItem s : localData.scopeStack) {
preCatches.addAll(toInsList(s.toSource(localData, this)));
if (s instanceof WithObjectAVM2Item) {
preCatches.add(ins(new PushWithIns()));
} else {
preCatches.add(ins(new PushScopeIns()));
}
}
preCatches.add(ins(new NewCatchIns(), aloneFinallyEx));
preCatches.addAll(toInsList(AssignableAVM2Item.dupSetTemp(localData, this, tempReg)));
preCatches.add(ins(new PushScopeIns()));
@@ -700,10 +758,14 @@ public class AVM2SourceGenerator implements SourceGenerator {
if (finallyEx > -1) {
List<AVM2Instruction> preCatches = new ArrayList<>();
preCatches.add(0, new ExceptionMarkAVM2Instruction(finallyEx, MARK_E_TARGET));
preCatches.add(ins(new GetLocal0Ins()));
preCatches.add(ins(new PushScopeIns()));
preCatches.add(AssignableAVM2Item.generateGetLoc(localData.activationReg));
preCatches.add(ins(new PushScopeIns()));
for (GraphTargetItem s : localData.scopeStack) {
preCatches.addAll(toInsList(s.toSource(localData, this)));
if (s instanceof WithObjectAVM2Item) {
preCatches.add(ins(new PushWithIns()));
} else {
preCatches.add(ins(new PushScopeIns()));
}
}
preCatches.add(ins(new NewCatchIns(), finallyEx));
preCatches.addAll(toInsList(AssignableAVM2Item.dupSetTemp(localData, this, tempReg)));
preCatches.add(ins(new PushScopeIns()));
@@ -769,7 +831,7 @@ public class AVM2SourceGenerator implements SourceGenerator {
}
ret.addAll(catches);
localData.exceptions.addAll(newex);
//localData.exceptions.addAll(newex);
if (finallyEx > -1) {
localData.finallyCatches.remove(localData.finallyCatches.size() - 1);
@@ -1192,8 +1254,14 @@ public class AVM2SourceGenerator implements SourceGenerator {
public int method(List<MethodBody> callStack, String pkg, boolean needsActivation, List<AssignableAVM2Item> subvariables, int initScope, boolean hasRest, int line, String className, String superType, boolean constructor, SourceGeneratorLocalData localData, List<GraphTargetItem> paramTypes, List<String> paramNames, List<GraphTargetItem> paramValues, List<GraphTargetItem> body, GraphTargetItem retType) throws CompilationException {
//Reference<Boolean> hasArgs = new Reference<>(Boolean.FALSE);
//calcRegisters(localData,needsActivation,paramNames,subvariables,body, hasArgs);
int oldActivationReg = localData.activationReg;
//calcRegisters(localData,needsActivation,paramNames,subvariables,body, hasArgs);
SourceGeneratorLocalData newlocalData = new SourceGeneratorLocalData(new HashMap<String, Integer>(), 1, true, 0);
newlocalData.currentClass = className;
newlocalData.pkg = localData.pkg;
newlocalData.callStack.addAll(localData.callStack);
newlocalData.traitUsages = localData.traitUsages;
localData = newlocalData;
localData.activationReg = 0;
for (int i = 0; i < subvariables.size(); i++) {
@@ -1221,8 +1289,11 @@ public class AVM2SourceGenerator implements SourceGenerator {
List<String> registerNames = new ArrayList<>();
List<String> registerTypes = new ArrayList<>();
if (className != null) {
registerTypes.add(pkg.isEmpty() ? className : pkg + "." + className);
String fullClassName = pkg.isEmpty() ? className : pkg + "." + className;
registerTypes.add(fullClassName);
localData.scopeStack.add(new LocalRegAVM2Item(null, registerNames.size(), null));
registerNames.add("this");
} else {
registerTypes.add("*");
registerNames.add("--nothis");
@@ -1251,6 +1322,7 @@ public class AVM2SourceGenerator implements SourceGenerator {
registerNames.add("+$activation");
localData.activationReg = registerNames.size() - 1;
registerTypes.add("Object");
localData.scopeStack.add(new LocalRegAVM2Item(null, localData.activationReg, null));
}
for (AssignableAVM2Item an : subvariables) {
if (an instanceof NameAVM2Item) {
@@ -1511,8 +1583,6 @@ public class AVM2SourceGenerator implements SourceGenerator {
mbody.autoFillStats(abc, initScope);
abc.addMethodBody(mbody);
localData.callStack.remove(mbody);
localData.activationReg = oldActivationReg;
return mbody.method_info;
}

View File

@@ -865,6 +865,7 @@ public class ActionScriptParser {
openedNamespaces.add(abc.constants.getNamespaceId(new Namespace(Namespace.KIND_PACKAGE /*FIXME?*/, abc.constants.getStringId(ns.toString(), true)), 0, true));
break;
case WITH:
needsActivation.setVal(true);
expectedType(SymbolType.PARENT_OPEN);
GraphTargetItem wvar = expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables);//(name(false, openedNamespaces, registerVars, inFunction, inMethod, variables));
if (!isNameOrProp(wvar)) {
@@ -872,9 +873,18 @@ public class ActionScriptParser {
}
expectedType(SymbolType.PARENT_CLOSE);
expectedType(SymbolType.CURLY_OPEN);
List<GraphTargetItem> wcmd = commands(needsActivation, importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, variables);
List<AssignableAVM2Item> withVars = new ArrayList<>();
List<GraphTargetItem> wcmd = commands(needsActivation, importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, withVars);
variables.addAll(withVars);
for (AssignableAVM2Item a : withVars) {
if (a instanceof UnresolvedAVM2Item) {
UnresolvedAVM2Item ua = (UnresolvedAVM2Item) a;
ua.scopeStack.add(0, wvar);
}
}
expectedType(SymbolType.CURLY_CLOSE);
ret = new WithAVM2Item(null, wvar, wcmd);
((WithAVM2Item) ret).subvariables = withVars;
break;
/*case DELETE:
GraphTargetItem varDel = expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables);//name(false, openedNamespaces, registerVars, inFunction, inMethod, variables);
@@ -1176,6 +1186,7 @@ public class ActionScriptParser {
List<List<GraphTargetItem>> catchCommands = new ArrayList<>();
List<NameAVM2Item> catchExceptions = new ArrayList<>();
int varCnt = variables.size();
List<List<AssignableAVM2Item>> catchesVars = new ArrayList<>();
while (s.type == SymbolType.CATCH) {
expectedType(SymbolType.PARENT_OPEN);
s = lex();
@@ -1188,10 +1199,30 @@ public class ActionScriptParser {
variables.add(e);
catchExceptions.add(e);
e.setSlotNumber(1);
e.setSlotScope(2); //?
e.setSlotScope(Integer.MAX_VALUE); //will be changed later
expectedType(SymbolType.PARENT_CLOSE);
List<GraphTargetItem> cc = new ArrayList<>();
cc.add(command(needsActivation, importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, true, variables));
List<AssignableAVM2Item> catchVars = new ArrayList<>();
cc.add(command(needsActivation, importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, true, catchVars));
catchesVars.add(catchVars);
variables.addAll(catchVars);
for (AssignableAVM2Item a : catchVars) {
if (a instanceof UnresolvedAVM2Item) {
UnresolvedAVM2Item ui = (UnresolvedAVM2Item) a;
if (ui.getVariableName().equals(e.getVariableName())) {
try {
ui.resolve(new ArrayList<GraphTargetItem>(), new ArrayList<String>(), abc, otherABCs, new ArrayList<MethodBody>(), variables);
} catch (CompilationException ex) {
//ignore
}
ui.setSlotNumber(e.getSlotNumber());
ui.setSlotScope(e.getSlotScope());
}
}
}
catchCommands.add(cc);
s = lex();
found = true;
@@ -1227,6 +1258,7 @@ public class ActionScriptParser {
}
lexer.pushback(s);
TryAVM2Item tai = new TryAVM2Item(tryCommands, null, catchCommands, finallyCommands);
tai.catchVariables = catchesVars;
tai.catchExceptions2 = catchExceptions;
ret = tai;
break;
@@ -1496,6 +1528,9 @@ public class ActionScriptParser {
}
private boolean isNameOrProp(GraphTargetItem item) {
if (item instanceof UnresolvedAVM2Item) {
return true; //we don't know yet
}
if (item instanceof NameAVM2Item) {
return true;
}

View File

@@ -62,6 +62,7 @@ public class PropertyAVM2Item extends AssignableAVM2Item {
public GraphTargetItem index;
private List<Integer> openedNamespaces;
private List<MethodBody> callStack;
public List<GraphTargetItem> scopeStack = new ArrayList<GraphTargetItem>();
@Override
public AssignableAVM2Item copy() {
@@ -96,113 +97,154 @@ public class PropertyAVM2Item extends AssignableAVM2Item {
String objType = object == null ? null : object.returnType().toString();
String propType = "";
int propIndex = 0;
if (objType == null) {
if (scopeStack.isEmpty()) { //Everything is multiname when with command
if (objType == null) {
for (MethodBody b : callStack) {
for (int i = 0; i < b.traits.traits.size(); i++) {
Trait t = b.traits.traits.get(i);
if (t.getName(abc).getName(abc.constants, new ArrayList<String>()).equals(propertyName)) {
if (t instanceof TraitSlotConst) {
TraitSlotConst tsc = (TraitSlotConst) t;
objType = "Function";
propType = tsc.type_index == 0 ? "*" : abc.constants.constant_multiname.get(tsc.type_index).getNameWithNamespace(abc.constants);
propIndex = tsc.name_index;
if (!localData.traitUsages.containsKey(b)) {
localData.traitUsages.put(b, new ArrayList<Integer>());
/*for (GraphTargetItem s : scopeStack) {
String oType = s.returnType().toString();
String name = oType;
String nsname = "";
if(name.contains(".")){
nsname = name.substring(0,name.lastIndexOf("."));
name = name.substring(name.lastIndexOf(".")+1);
}
List<ABC> abcs = new ArrayList<>();
abcs.add(abc);
abcs.addAll(otherABCs);
loopabc:
for (ABC a : abcs) {
for (int h = 0; h < a.instance_info.size(); h++) {
InstanceInfo ii = a.instance_info.get(h);
Multiname n = a.constants.constant_multiname.get(ii.name_index);
if (name.equals(n.getName(a.constants, new ArrayList<String>())) && n.getNamespace(a.constants).hasName(nsname,a.constants)) {
Reference<String> outName = new Reference<>("");
Reference<String> outNs = new Reference<>("");
Reference<String> outPropNs = new Reference<>("");
Reference<Integer> outPropNsKind = new Reference<>(1);
Reference<String> outPropType = new Reference<>("");
if (AVM2SourceGenerator.searchPrototypeChain(false, abcs, nsname, name, propertyName, outName, outNs, outPropNs, outPropNsKind, outPropType)) {
objType = "".equals(outNs.getVal()) ? outName.getVal() : outNs.getVal() + "." + outName.getVal();
propType = outPropType.getVal();
propIndex = abc.constants.getMultinameId(new Multiname(Multiname.QNAME,
abc.constants.getStringId(propertyName, true),
abc.constants.getNamespaceId(new Namespace(outPropNsKind.getVal(), abc.constants.getStringId(outPropNs.getVal(), true)), 0, true), 0, 0, new ArrayList<Integer>()), true
);
break loopabc;
}
}
}
}
}*/
}
if (objType == null) {
for (MethodBody b : callStack) {
for (int i = 0; i < b.traits.traits.size(); i++) {
Trait t = b.traits.traits.get(i);
if (t.getName(abc).getName(abc.constants, new ArrayList<String>()).equals(propertyName)) {
if (t instanceof TraitSlotConst) {
TraitSlotConst tsc = (TraitSlotConst) t;
objType = "Function";
propType = tsc.type_index == 0 ? "*" : abc.constants.constant_multiname.get(tsc.type_index).getNameWithNamespace(abc.constants);
propIndex = tsc.name_index;
if (!localData.traitUsages.containsKey(b)) {
localData.traitUsages.put(b, new ArrayList<Integer>());
}
localData.traitUsages.get(b).add(i);
}
localData.traitUsages.get(b).add(i);
}
}
}
}
if (objType == null) {
loopobjType:
for (int i = 0; i < openedNamespaces.size(); i++) {
int nsindex = openedNamespaces.get(i);
int nsKind = abc.constants.constant_namespace.get(openedNamespaces.get(i)).kind;
String nsname = abc.constants.constant_namespace.get(openedNamespaces.get(i)).getName(abc.constants);
int name_index = 0;
for (int m = 1; m < abc.constants.constant_multiname.size(); m++) {
Multiname mname = abc.constants.constant_multiname.get(m);
if (mname.kind == Multiname.QNAME && mname.getName(abc.constants, new ArrayList<String>()).equals(propertyName) && mname.namespace_index == nsindex) {
name_index = m;
break;
}
}
if (name_index > 0) {
for (int c = 0; c < abc.instance_info.size(); c++) {
for (Trait t : abc.instance_info.get(c).instance_traits.traits) {
if (t.name_index == name_index) {
objType = abc.instance_info.get(c).getName(abc.constants).getNameWithNamespace(abc.constants);
propType = AVM2SourceGenerator.getTraitReturnType(abc, t).toString();
propIndex = t.name_index;
break loopobjType;
}
}
for (Trait t : abc.class_info.get(c).static_traits.traits) {
if (t.name_index == name_index) {
objType = abc.instance_info.get(c).getName(abc.constants).getNameWithNamespace(abc.constants);
propType = AVM2SourceGenerator.getTraitReturnType(abc, t).toString();
propIndex = t.name_index;
break loopobjType;
}
if (objType == null) {
loopobjType:
for (int i = 0; i < openedNamespaces.size(); i++) {
int nsindex = openedNamespaces.get(i);
int nsKind = abc.constants.constant_namespace.get(openedNamespaces.get(i)).kind;
String nsname = abc.constants.constant_namespace.get(openedNamespaces.get(i)).getName(abc.constants);
int name_index = 0;
for (int m = 1; m < abc.constants.constant_multiname.size(); m++) {
Multiname mname = abc.constants.constant_multiname.get(m);
if (mname.kind == Multiname.QNAME && mname.getName(abc.constants, new ArrayList<String>()).equals(propertyName) && mname.namespace_index == nsindex) {
name_index = m;
break;
}
}
}
if (nsKind == Namespace.KIND_PACKAGE) {
List<ABC> abcs = new ArrayList<>();
abcs.add(abc);
abcs.addAll(otherABCs);
loopabc:
for (ABC a : otherABCs) {
for (int h = 0; h < a.instance_info.size(); h++) {
InstanceInfo ii = a.instance_info.get(h);
Multiname n = a.constants.constant_multiname.get(ii.name_index);
if (n.getNamespace(a.constants).kind == Namespace.KIND_PACKAGE && n.getNamespace(a.constants).getName(a.constants).equals(nsname)) {
Reference<String> outName = new Reference<>("");
Reference<String> outNs = new Reference<>("");
Reference<String> outPropNs = new Reference<>("");
Reference<Integer> outPropNsKind = new Reference<>(1);
Reference<String> outPropType = new Reference<>("");
if (AVM2SourceGenerator.searchPrototypeChain(false, abcs, nsname, n.getName(a.constants, new ArrayList<String>()), propertyName, outName, outNs, outPropNs, outPropNsKind, outPropType)) {
objType = "".equals(outNs.getVal()) ? outName.getVal() : outNs.getVal() + "." + outName.getVal();
propType = outPropType.getVal();
propIndex = abc.constants.getMultinameId(new Multiname(Multiname.QNAME,
abc.constants.getStringId(propertyName, true),
abc.constants.getNamespaceId(new Namespace(outPropNsKind.getVal(), abc.constants.getStringId(outPropNs.getVal(), true)), 0, true), 0, 0, new ArrayList<Integer>()), true
);
if (name_index > 0) {
for (int c = 0; c < abc.instance_info.size(); c++) {
for (Trait t : abc.instance_info.get(c).instance_traits.traits) {
if (t.name_index == name_index) {
objType = abc.instance_info.get(c).getName(abc.constants).getNameWithNamespace(abc.constants);
propType = AVM2SourceGenerator.getTraitReturnType(abc, t).toString();
propIndex = t.name_index;
break loopobjType;
}
}
for (Trait t : abc.class_info.get(c).static_traits.traits) {
if (t.name_index == name_index) {
objType = abc.instance_info.get(c).getName(abc.constants).getNameWithNamespace(abc.constants);
propType = AVM2SourceGenerator.getTraitReturnType(abc, t).toString();
propIndex = t.name_index;
break loopobjType;
}
}
}
}
if (nsKind == Namespace.KIND_PACKAGE) {
List<ABC> abcs = new ArrayList<>();
abcs.add(abc);
abcs.addAll(otherABCs);
loopabc:
for (ABC a : otherABCs) {
for (int h = 0; h < a.instance_info.size(); h++) {
InstanceInfo ii = a.instance_info.get(h);
Multiname n = a.constants.constant_multiname.get(ii.name_index);
if (n.getNamespace(a.constants).kind == Namespace.KIND_PACKAGE && n.getNamespace(a.constants).getName(a.constants).equals(nsname)) {
Reference<String> outName = new Reference<>("");
Reference<String> outNs = new Reference<>("");
Reference<String> outPropNs = new Reference<>("");
Reference<Integer> outPropNsKind = new Reference<>(1);
Reference<String> outPropType = new Reference<>("");
if (AVM2SourceGenerator.searchPrototypeChain(false, abcs, nsname, n.getName(a.constants, new ArrayList<String>()), propertyName, outName, outNs, outPropNs, outPropNsKind, outPropType)) {
objType = "".equals(outNs.getVal()) ? outName.getVal() : outNs.getVal() + "." + outName.getVal();
propType = outPropType.getVal();
propIndex = abc.constants.getMultinameId(new Multiname(Multiname.QNAME,
abc.constants.getStringId(propertyName, true),
abc.constants.getNamespaceId(new Namespace(outPropNsKind.getVal(), abc.constants.getStringId(outPropNs.getVal(), true)), 0, true), 0, 0, new ArrayList<Integer>()), true
);
break loopobjType;
}
}
}
}
}
}
}
}
} else {
List<ABC> abcs = new ArrayList<>();
abcs.add(abc);
abcs.addAll(otherABCs);
loopa:
for (ABC a : abcs) {
for (InstanceInfo ii : a.instance_info) {
Multiname m = ii.getName(a.constants);
if (m.getNameWithNamespace(a.constants).equals(objType)) {
Reference<String> outName = new Reference<>("");
Reference<String> outNs = new Reference<>("");
Reference<String> outPropNs = new Reference<>("");
Reference<Integer> outPropNsKind = new Reference<>(1);
Reference<String> outPropType = new Reference<>("");
if (AVM2SourceGenerator.searchPrototypeChain(false, abcs, m.getNamespace(a.constants).getName(a.constants), m.getName(a.constants, new ArrayList<String>()), propertyName, outName, outNs, outPropNs, outPropNsKind, outPropType)) {
objType = "".equals(outNs.getVal()) ? outName.getVal() : outNs.getVal() + "." + outName.getVal();
propType = outPropType.getVal();
propIndex = abc.constants.getMultinameId(new Multiname(Multiname.QNAME,
abc.constants.getStringId(propertyName, true),
abc.constants.getNamespaceId(new Namespace(outPropNsKind.getVal(), abc.constants.getStringId(outPropNs.getVal(), true)), 0, true), 0, 0, new ArrayList<Integer>()), true
);
} else {
List<ABC> abcs = new ArrayList<>();
abcs.add(abc);
abcs.addAll(otherABCs);
loopa:
for (ABC a : abcs) {
for (InstanceInfo ii : a.instance_info) {
Multiname m = ii.getName(a.constants);
if (m.getNameWithNamespace(a.constants).equals(objType)) {
Reference<String> outName = new Reference<>("");
Reference<String> outNs = new Reference<>("");
Reference<String> outPropNs = new Reference<>("");
Reference<Integer> outPropNsKind = new Reference<>(1);
Reference<String> outPropType = new Reference<>("");
if (AVM2SourceGenerator.searchPrototypeChain(false, abcs, m.getNamespace(a.constants).getName(a.constants), m.getName(a.constants, new ArrayList<String>()), propertyName, outName, outNs, outPropNs, outPropNsKind, outPropType)) {
objType = "".equals(outNs.getVal()) ? outName.getVal() : outNs.getVal() + "." + outName.getVal();
propType = outPropType.getVal();
propIndex = abc.constants.getMultinameId(new Multiname(Multiname.QNAME,
abc.constants.getStringId(propertyName, true),
abc.constants.getNamespaceId(new Namespace(outPropNsKind.getVal(), abc.constants.getStringId(outPropNs.getVal(), true)), 0, true), 0, 0, new ArrayList<Integer>()), true
);
break loopa;
break loopa;
}
}
}
}
@@ -459,7 +501,7 @@ public class PropertyAVM2Item extends AssignableAVM2Item {
String cname;
String pkgName = "";
cname = localData.currentClass;
if (cname.contains(".")) {
if (cname != null && cname.contains(".")) {
pkgName = cname.substring(0, cname.lastIndexOf('.'));
cname = cname.substring(cname.lastIndexOf('.') + 1);
}
@@ -471,7 +513,7 @@ public class PropertyAVM2Item extends AssignableAVM2Item {
List<ABC> abcs = new ArrayList<>();
abcs.add(abc);
abcs.addAll(otherABCs);
if (AVM2SourceGenerator.searchPrototypeChain(true, abcs, pkgName, cname, propertyName, outName, outNs, outPropNs, outPropNsKind, outPropType)) {
if (cname != null && AVM2SourceGenerator.searchPrototypeChain(true, abcs, pkgName, cname, propertyName, outName, outNs, outPropNs, outPropNsKind, outPropType)) {
NameAVM2Item nobj = new NameAVM2Item(new TypeItem(localData.currentClass), 0, "this", null, false, openedNamespaces);
nobj.setRegNumber(0);
obj = nobj;

View File

@@ -58,6 +58,7 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item {
public GraphTargetItem resolved;
private boolean mustBeType;
public List<String> importedClasses;
public List<GraphTargetItem> scopeStack = new ArrayList<GraphTargetItem>();
@Override
public AssignableAVM2Item copy() {
@@ -302,33 +303,35 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item {
return resolved;
}
//search for variable
for (AssignableAVM2Item a : variables) {
if (a instanceof NameAVM2Item) {
NameAVM2Item n = (NameAVM2Item) a;
if (n.isDefinition() && parts.get(0).equals(n.getVariableName())) {
NameAVM2Item ret = new NameAVM2Item(n.type, n.line, parts.get(0), null, false, openedNamespaces);
ret.setSlotScope(n.getSlotScope());
ret.setSlotNumber(n.getSlotNumber());
ret.setRegNumber(n.getRegNumber());
resolved = ret;
for (int i = 1; i < parts.size(); i++) {
resolved = new PropertyAVM2Item(resolved, parts.get(i), null, abc, otherAbcs, openedNamespaces, new ArrayList<MethodBody>());
if (i == parts.size() - 1) {
((PropertyAVM2Item) resolved).index = index;
((PropertyAVM2Item) resolved).assignedValue = assignedValue;
if (scopeStack.isEmpty()) { //Everything is multiname property in with command
//search for variable
for (AssignableAVM2Item a : variables) {
if (a instanceof NameAVM2Item) {
NameAVM2Item n = (NameAVM2Item) a;
if (n.isDefinition() && parts.get(0).equals(n.getVariableName())) {
NameAVM2Item ret = new NameAVM2Item(n.type, n.line, parts.get(0), null, false, openedNamespaces);
ret.setSlotScope(n.getSlotScope());
ret.setSlotNumber(n.getSlotNumber());
ret.setRegNumber(n.getRegNumber());
resolved = ret;
for (int i = 1; i < parts.size(); i++) {
resolved = new PropertyAVM2Item(resolved, parts.get(i), null, abc, otherAbcs, openedNamespaces, new ArrayList<MethodBody>());
if (i == parts.size() - 1) {
((PropertyAVM2Item) resolved).index = index;
((PropertyAVM2Item) resolved).assignedValue = assignedValue;
}
}
if (parts.size() == 1) {
ret.setIndex(index);
ret.setAssignedValue(assignedValue);
}
ret.setNs(n.getNs());
return ret;
}
if (parts.size() == 1) {
ret.setIndex(index);
ret.setAssignedValue(assignedValue);
}
ret.setNs(n.getNs());
return ret;
}
}
}
//Search for types in imported classes
for (String imp : importedClasses) {
String impName = imp;
@@ -415,6 +418,7 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item {
for (int i = 0; i < parts.size(); i++) {
resolved = new PropertyAVM2Item(resolved, parts.get(i), (i == parts.size() - 1) ? index : null, abc, otherAbcs, openedNamespaces, callStack);
if (ret == null) {
((PropertyAVM2Item) resolved).scopeStack = scopeStack;
ret = resolved;
}
}

View File

@@ -2,8 +2,6 @@ TODO List for AS3 parser/compiler:
------------------------------
- E4X (XML)
- typenames (Vectors)
- with
- try/catch scopes (with, inner functions - no this)
- inner function names
- delete property
- default xml namespace