AS3 parser: typenames (Vector)

This commit is contained in:
Jindra Petk
2014-04-13 18:51:59 +02:00
parent 66e9a650b8
commit 7324cedaff
14 changed files with 784 additions and 722 deletions

View File

@@ -50,7 +50,7 @@ public class GetPropertyIns extends InstructionDefinition {
int ret = -1 + 1;
int multinameIndex = ins.operands[0];
int kind = abc.constants.getMultiname(multinameIndex).kind;
if (kind != Multiname.MULTINAMEL && kind != Multiname.MULTINAMELA) {
if (kind != Multiname.MULTINAMEL && kind != Multiname.MULTINAMELA) { //FIXME!!!
if (abc.constants.getMultiname(multinameIndex).needsName()) {
ret--;
}

View File

@@ -135,7 +135,7 @@ public class SetPropertyIns extends InstructionDefinition implements SetTypeIns
int ret = -2;
int multinameIndex = ins.operands[0];
int multinameKind = abc.constants.getMultiname(multinameIndex).kind;
if (multinameKind == Multiname.MULTINAMEL || multinameKind == Multiname.MULTINAMELA) {
if (multinameKind == Multiname.MULTINAMEL || multinameKind == Multiname.MULTINAMELA) { //FIXME!!!
return 0;
}
if (abc.constants.getMultiname(multinameIndex).needsName()) {

View File

@@ -61,6 +61,6 @@ public class ApplyTypeIns extends InstructionDefinition {
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -ins.operands[0] + 1;
return -ins.operands[0] - 1 + 1;
}
}

View File

@@ -347,7 +347,7 @@ public class AVM2SourceGenerator implements SourceGenerator {
ins(new PushByteIns(), 0),
AssignableAVM2Item.setTemp(localData, this, counterReg),
collection,
NameAVM2Item.generateCoerce(this, "*"),
NameAVM2Item.generateCoerce(this, TypeItem.UNBOUNDED),
AssignableAVM2Item.setTemp(localData, this, collectionReg)
));
@@ -1180,45 +1180,27 @@ public class AVM2SourceGenerator implements SourceGenerator {
return 0;
}
TypeItem nameItem = (TypeItem) type;
TypeItem nameItem = (TypeItem) type;
name = nameItem.fullTypeName;
if (name.contains(".")) {
pkg = name.substring(0, name.lastIndexOf('.'));
name = name.substring(name.lastIndexOf('.') + 1);
}
/*int nsKind = Namespace.KIND_PACKAGE;
if (pkg.equals("")) {
for (int i = 0; i < nameItem.openedNamespaces.size(); i++) {
String ns = nameItem.openedNamespaces.get(i);
String nspkg = ns;
String nsclass = null;
if (nspkg.contains(":")) {
nsclass = nspkg.substring(nspkg.indexOf(":") + 1);
nspkg = nspkg.substring(0, nspkg.indexOf(":"));
}
if (nsclass == null) {
List<ABC> abcs = new ArrayList<>();
abcs.add(abc);
abcs.addAll(allABCs);
loopabc:
for (ABC a : abcs) {
for (InstanceInfo ii : a.instance_info) {
Multiname n = a.constants.constant_multiname.get(ii.name_index);
if (n.getNamespace(a.constants).getName(a.constants).equals(nspkg) && n.getName(a.constants, new ArrayList<String>()).equals(name)) {
pkg = nspkg;
nsKind = n.getNamespace(a.constants).kind;
break loopabc;
}
}
}
} else if (name.equals(nsclass)) {
pkg = nspkg;
nsKind = nameItem.openedNamespacesKind.get(i);
break;
}
}
}*/
return abc.constants.getMultinameId(new Multiname(Multiname.QNAME, str(name), namespace(Namespace.KIND_PACKAGE/*?*/, pkg), 0, 0, new ArrayList<Integer>()), true);
if(!nameItem.subtypes.isEmpty()){ //It's vector => TypeName
List<Integer> params = new ArrayList<>();
for(String p:nameItem.subtypes){
String ppkg = "";
if (p.contains(".")) {
ppkg = p.substring(0, p.lastIndexOf('.'));
p = p.substring(p.lastIndexOf('.') + 1);
}
params.add(abc.constants.getMultinameId(new Multiname(Multiname.QNAME, str(p), namespace(Namespace.KIND_PACKAGE/*?*/, ppkg), 0, 0, new ArrayList<Integer>()), true));
}
int qname = abc.constants.getMultinameId(new Multiname(Multiname.QNAME, str(name), namespace(Namespace.KIND_PACKAGE/*?*/, pkg), 0, 0, new ArrayList<Integer>()), true);
return abc.constants.getMultinameId(new Multiname(Multiname.TYPENAME, 0,0, 0, qname, params), true);
}else{
return abc.constants.getMultinameId(new Multiname(Multiname.QNAME, str(name), namespace(Namespace.KIND_PACKAGE/*?*/, pkg), 0, 0, new ArrayList<Integer>()), true);
}
}
public int ident(GraphTargetItem name) {

View File

@@ -208,142 +208,36 @@ public class ActionScriptParser {
name += "." + s.value.toString();
s = lex();
}
List<String> params=new ArrayList<>();
if(s.type == SymbolType.TYPENAME){
s = lex();
do{
String p = "";
expected(s, lexer.yyline(), SymbolType.IDENTIFIER);
p = s.value.toString();
s = lex();
while (s.type == SymbolType.DOT) {
s = lex();
expected(s, lexer.yyline(), SymbolType.IDENTIFIER);
name += "." + s.value.toString();
s = lex();
}
params.add(p);
}while(s.type == SymbolType.COMMA);
expected(s, lexer.yyline(), SymbolType.GREATER_THAN);
s = lex();
/*if(!openedNamespaces.contains(AS3vecNs)){
openedNamespaces.add(AS3vecNs);
} */
}
GraphTargetItem index = null;
if (s.type == SymbolType.BRACKET_OPEN) {
index = expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables);
expectedType(SymbolType.BRACKET_CLOSE);
} else {
lexer.pushback(s);
}
if (!typeOnly) {
/*for (NameAVM2Item n : variables) {
if (n.getVariableName().equals(parts.get(0))) {
NameAVM2Item ni = new NameAVM2Item(n.type, lexer.yyline(), n.getVariableName(), null, false, openedNamespaces);
variables.add(ni);
GraphTargetItem ret = ni;
if (parts.size() == 1) {
((NameAVM2Item) ret).setIndex(index);
}
for (int i = 1; i < parts.size(); i++) {
ret = new PropertyAVM2Item(ret, parts.get(i), i == parts.size() - 1 ? index : null, abc, otherABCs, openedNamespaces);
}
return ret;
}
}*/
}
/*List<ABC> allAbcs = new ArrayList<>();
allAbcs.add(abc);
allAbcs.addAll(otherABCs);
//search for variable in openedNamespaces
if (!typeOnly) {
for (int i = 0; i < openedNamespaces.size(); i++) {
int nsIndex = openedNamespaces.get(i);
Namespace ns = abc.constants.constant_namespace.get(nsIndex);
int nsKind = ns.kind;
loopabc:
for (ABC a : allAbcs) {
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).getName(a.constants).equals(ns.getName(abc.constants)) && n.getNamespace(a.constants).kind == nsKind) {
//found opened class
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, allAbcs, n.getNamespace(a.constants).getName(a.constants), n.getName(a.constants, new ArrayList<String>()), parts.get(0), outName, outNs, outPropNs, outPropNsKind, outPropType)) {
return new PropertyAVM2Item(null, parts.get(0), index, abc, otherABCs, openedNamespaces);
}
}
}
}
}
}
//variable not found, gonna search types
String pkg = "";
String name = null;
int foundNsKind = Namespace.KIND_PACKAGE;
int k;
loopk:
for (k = parts.size() - 1; k >= 0; k--) {
if (typeOnly) {
if (k < parts.size() - 1) {
k = -1;
break loopk;
}
}
if (k == 0 || typeOnly) {
for (int i = 0; i < importedClasses.size(); i++) {
String iname = importedClasses.get(i);
String ipkg = "";
if (iname.contains(".")) {
ipkg = iname.substring(0, iname.lastIndexOf('.'));
iname = iname.substring(iname.lastIndexOf('.') + 1);
}
if (iname.equals(parts.get(0))) {
k = 0;
pkg = ipkg;
name = iname;
break loopk;
}
}
}
pkg = "";
for (int j = 0; j <= k - 1; j++) {
if (!"".equals(pkg)) {
pkg += ".";
}
pkg += parts.get(j);
}
name = parts.get(k);
String fname = pkg.isEmpty() ? name : pkg + "." + name;
for (ABC a : allAbcs) {
int c = a.findClassByName(fname);
if (c != -1) {
break loopk;
}
}
for (int i = 0; i < openedNamespaces.size(); i++) {
int nsIndex = openedNamespaces.get(i);
Namespace ns = abc.constants.constant_namespace.get(nsIndex);
int nsKind = ns.kind;
String nsname = ns.getName(abc.constants);
if (nsKind == Namespace.KIND_PACKAGE) {
for (ABC a : allAbcs) {
int c = a.findClassByName(nsname.isEmpty() ? fname : nsname + "." + fname);
if (c != -1) {
pkg = nsname;
break loopk;
}
}
}
}
}
if (k == -1) {
NameAVM2Item ret = new NameAVM2Item(null, lexer.yyline(), Helper.joinStrings(parts, "."), null, false, openedNamespaces);
ret.unresolved = true;
ret.setIndex(index);
variables.add(ret);
return ret;
//throw new ParseException("Cannot find variable or type:" + Helper.joinStrings(parts, "."), lexer.yyline());
}
GraphTargetItem ret = new TypeItem("".equals(pkg) ? name : pkg + "." + name);
for (int i = 1; i < parts.size(); i++) {
ret = new PropertyAVM2Item(ret, parts.get(i), i == parts.size() - 1 ? index : null, abc, otherABCs, openedNamespaces);
}*/
UnresolvedAVM2Item ret = new UnresolvedAVM2Item(importedClasses, typeOnly, null, lexer.yyline(), name, null, openedNamespaces);
}
UnresolvedAVM2Item ret = new UnresolvedAVM2Item(params,importedClasses, typeOnly, null, lexer.yyline(), name, null, openedNamespaces);
ret.setIndex(index);
variables.add(ret);
return ret;
@@ -408,6 +302,7 @@ public class ActionScriptParser {
}
private FunctionAVM2Item function(Reference<Boolean> needsActivation, List<String> importedClasses, int namespace, GraphTargetItem thisType, List<Integer> openedNamespaces, boolean withBody, String functionName, boolean isMethod, List<AssignableAVM2Item> variables) throws IOException, ParseException {
openedNamespaces = new ArrayList<>(openedNamespaces); //local copy
int line = lexer.yyline();
ParsedSymbol s;
expectedType(SymbolType.PARENT_OPEN);
@@ -1752,7 +1647,7 @@ public class ActionScriptParser {
case NEW:
GraphTargetItem newvar = name(needsActivation, true, openedNamespaces, registerVars, inFunction, inMethod, variables, importedClasses);
expectedType(SymbolType.PARENT_OPEN);
ret = new ConstructSomethingAVM2Item(newvar, call(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, variables));
ret = new ConstructSomethingAVM2Item(openedNamespaces,newvar, call(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, variables));
existsRemainder = true;
break;
case IDENTIFIER:
@@ -1825,7 +1720,7 @@ public class ActionScriptParser {
int packageInternalNs = 0;
openedNamespaces.add(packageInternalNs = abc.constants.getNamespaceId(new Namespace(Namespace.KIND_PACKAGE_INTERNAL, abc.constants.getStringId(name, true)), 0, true));
openedNamespaces.add(publicNs = abc.constants.getNamespaceId(new Namespace(Namespace.KIND_PACKAGE, abc.constants.getStringId("", true)), 0, true));
openedNamespaces.add(abc.constants.addNamespace(new Namespace(Namespace.KIND_PRIVATE, 0))); //abc.constants.getStringId(fileName + "$", true)
if (!name.isEmpty()) {
openedNamespaces.add(publicNs = abc.constants.getNamespaceId(new Namespace(Namespace.KIND_PACKAGE, abc.constants.getStringId(name, true)), 0, true));

View File

@@ -17,9 +17,16 @@
package com.jpexs.decompiler.flash.abc.avm2.parser.script;
import com.jpexs.decompiler.flash.SourceGeneratorLocalData;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.ConstructIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.ConstructPropIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.other.FindPropertyStrictIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.other.GetLexIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.types.ApplyTypeIns;
import com.jpexs.decompiler.flash.abc.types.Multiname;
import com.jpexs.decompiler.flash.abc.types.Namespace;
import com.jpexs.decompiler.flash.abc.types.NamespaceSet;
import com.jpexs.decompiler.graph.CompilationException;
import com.jpexs.decompiler.graph.GraphSourceItem;
import com.jpexs.decompiler.graph.GraphTargetItem;
@@ -34,8 +41,11 @@ import java.util.List;
*/
public class ConstructSomethingAVM2Item extends CallAVM2Item {
public ConstructSomethingAVM2Item(GraphTargetItem name, List<GraphTargetItem> arguments) {
public List<Integer> openedNamespaces;
public ConstructSomethingAVM2Item(List<Integer> openedNamespaces,GraphTargetItem name, List<GraphTargetItem> arguments) {
super(name, arguments);
this.openedNamespaces = openedNamespaces;
}
@Override
@@ -43,6 +53,16 @@ public class ConstructSomethingAVM2Item extends CallAVM2Item {
return name.returnType();
}
private int allNsSetWithVec(ABC abc) {
int nssa[] = new int[openedNamespaces.size()+1];
for (int i = 0; i < openedNamespaces.size(); i++) {
nssa[i] = openedNamespaces.get(i);
}
nssa[nssa.length-1] = abc.constants.getNamespaceId(new Namespace(Namespace.KIND_PACKAGE, abc.constants.getStringId("__AS3__.vec", true)), 0, true);
return abc.constants.getNamespaceSetId(new NamespaceSet(nssa), true);
}
@Override
public List<GraphSourceItem> toSource(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException {
@@ -53,11 +73,33 @@ public class ConstructSomethingAVM2Item extends CallAVM2Item {
if (resname instanceof TypeItem) {
TypeItem prop = (TypeItem) resname;
if(!prop.subtypes.isEmpty()){ //It's Vector - TypeName
//int qname = ((AVM2SourceGenerator) generator).resolveType(prop.fullTypeName);
String name = prop.fullTypeName.substring(prop.fullTypeName.lastIndexOf(".")+1);
ABC abc=((AVM2SourceGenerator)generator).abc;
int qname = abc.constants.getMultinameId(new Multiname(Multiname.MULTINAME,abc.constants.getStringId(name,true) , 0,allNsSetWithVec(abc), 0, new ArrayList<Integer>()), true);
List<Integer> params=new ArrayList<>();
for(String p:prop.subtypes){
params.add(((AVM2SourceGenerator) generator).resolveType(p));
}
List<GraphSourceItem> ret=new ArrayList<>();
ret.add(ins(new GetLexIns(),qname));
for(int p:params){
ret.add(ins(new GetLexIns(),p));
}
ret.add(ins(new ApplyTypeIns(),params.size()));
ret.addAll(toSourceMerge(localData, generator, arguments,
ins(new ConstructIns(),arguments.size())
));
return ret;
}else{
int type_index = ((AVM2SourceGenerator) generator).resolveType(resname.toString());
return toSourceMerge(localData, generator,
new AVM2Instruction(0, new FindPropertyStrictIns(), new int[]{type_index, arguments.size()}, new byte[0]), arguments,
new AVM2Instruction(0, new ConstructPropIns(), new int[]{type_index, arguments.size()}, new byte[0])
);
}
}
if (resname instanceof NameAVM2Item) {
//TODO

View File

@@ -52,6 +52,7 @@ 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 com.jpexs.decompiler.graph.model.UnboundedTypeItem;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -198,22 +199,36 @@ public class NameAVM2Item extends AssignableAVM2Item {
}
}
public static AVM2Instruction generateCoerce(SourceGenerator generator, String type) {
public static AVM2Instruction generateCoerce(SourceGenerator generator, GraphTargetItem ttype) {
if (ttype instanceof UnresolvedAVM2Item) {
ttype = ((UnresolvedAVM2Item) ttype).resolved;
}
AVM2Instruction ins;
switch (type) {
case "int":
ins = ins(new ConvertIIns());
break;
case "*":
ins = ins(new CoerceAIns());
break;
case "String":
ins = ins(new CoerceSIns());
break;
default:
int type_index = new TypeItem(type).resolveClass(((AVM2SourceGenerator) generator).abc);
if (ttype instanceof UnboundedTypeItem) {
ins = ins(new CoerceAIns());
} else {
TypeItem type = (TypeItem) ttype;
if (type.subtypes.isEmpty()) {
switch (type.fullTypeName) {
case "int":
ins = ins(new ConvertIIns());
break;
case "*":
ins = ins(new CoerceAIns());
break;
case "String":
ins = ins(new CoerceSIns());
break;
default:
int type_index = type.resolveClass(((AVM2SourceGenerator) generator).abc);
ins = ins(new CoerceIns(), type_index);
break;
}
} else {
int type_index = type.resolveClass(((AVM2SourceGenerator) generator).abc);
ins = ins(new CoerceIns(), type_index);
break;
}
}
return ins;
}
@@ -233,8 +248,8 @@ public class NameAVM2Item extends AssignableAVM2Item {
if (variableName == null && ns != null && index != null) {
if (assignedValue != null) {
return toSourceMerge(localData, generator,
ns, generateCoerce(generator, "Namespace"), index, ins(new ConvertSIns()), ins(new FindPropertyStrictIns(), g.abc.constants.getMultinameId(new Multiname(Multiname.RTQNAMEL, 0, 0, 0, 0, new ArrayList<Integer>()), true)),
ns, generateCoerce(generator, "Namespace"), index, ins(new ConvertSIns()), assignedValue,
ns, generateCoerce(generator, new TypeItem("Namespace")), index, ins(new ConvertSIns()), ins(new FindPropertyStrictIns(), g.abc.constants.getMultinameId(new Multiname(Multiname.RTQNAMEL, 0, 0, 0, 0, new ArrayList<Integer>()), true)),
ns, generateCoerce(generator, new TypeItem("Namespace")), index, ins(new ConvertSIns()), assignedValue,
needsReturn ? dupSetTemp(localData, generator, ret_temp) : null,
ins(new SetPropertyIns(), g.abc.constants.getMultinameId(new Multiname(Multiname.RTQNAMEL, 0, 0, 0, 0, new ArrayList<Integer>()), true)),
needsReturn ? getTemp(localData, generator, ret_temp) : null,
@@ -242,8 +257,8 @@ public class NameAVM2Item extends AssignableAVM2Item {
);
} else {
return toSourceMerge(localData, generator,
ns, generateCoerce(generator, "Namespace"), index, ins(new ConvertSIns()), ins(new FindPropertyStrictIns(), g.abc.constants.getMultinameId(new Multiname(Multiname.RTQNAMEL, 0, 0, 0, 0, new ArrayList<Integer>()), true)),
ns, generateCoerce(generator, "Namespace"), index, ins(new ConvertSIns()), ins(new GetPropertyIns(), g.abc.constants.getMultinameId(new Multiname(Multiname.RTQNAMEL, 0, 0, 0, 0, new ArrayList<Integer>()), true)),
ns, generateCoerce(generator, new TypeItem("Namespace")), index, ins(new ConvertSIns()), ins(new FindPropertyStrictIns(), g.abc.constants.getMultinameId(new Multiname(Multiname.RTQNAMEL, 0, 0, 0, 0, new ArrayList<Integer>()), true)),
ns, generateCoerce(generator, new TypeItem("Namespace")), index, ins(new ConvertSIns()), ins(new GetPropertyIns(), g.abc.constants.getMultinameId(new Multiname(Multiname.RTQNAMEL, 0, 0, 0, 0, new ArrayList<Integer>()), true)),
needsReturn ? null : ins(new PopIns()),
killTemp(localData, generator, Arrays.asList(ns_temp, index_temp, ret_temp))
);
@@ -252,8 +267,8 @@ public class NameAVM2Item extends AssignableAVM2Item {
if (variableName != null && ns != null && index == null) {
if (assignedValue != null) {
return toSourceMerge(localData, generator,
ns, generateCoerce(generator, "Namespace"), ins(new FindPropertyStrictIns(), g.abc.constants.getMultinameId(new Multiname(Multiname.RTQNAME, g.abc.constants.getStringId(variableName, true), 0, 0, 0, new ArrayList<Integer>()), true)),
ns, generateCoerce(generator, "Namespace"), assignedValue,
ns, generateCoerce(generator, new TypeItem("Namespace")), ins(new FindPropertyStrictIns(), g.abc.constants.getMultinameId(new Multiname(Multiname.RTQNAME, g.abc.constants.getStringId(variableName, true), 0, 0, 0, new ArrayList<Integer>()), true)),
ns, generateCoerce(generator, new TypeItem("Namespace")), assignedValue,
needsReturn ? dupSetTemp(localData, generator, ret_temp) : null,
ins(new SetPropertyIns(), g.abc.constants.getMultinameId(new Multiname(Multiname.RTQNAME, g.abc.constants.getStringId(variableName, true), 0, 0, 0, new ArrayList<Integer>()), true)),
needsReturn ? getTemp(localData, generator, ret_temp) : null,
@@ -261,8 +276,8 @@ public class NameAVM2Item extends AssignableAVM2Item {
);
} else {
return toSourceMerge(localData, generator,
ns, generateCoerce(generator, "Namespace"), ins(new FindPropertyStrictIns(), g.abc.constants.getMultinameId(new Multiname(Multiname.RTQNAME, g.abc.constants.getStringId(variableName, true), 0, 0, 0, new ArrayList<Integer>()), true)),
ns, generateCoerce(generator, "Namespace"), ins(new GetPropertyIns(), g.abc.constants.getMultinameId(new Multiname(Multiname.RTQNAME, g.abc.constants.getStringId(variableName, true), 0, 0, 0, new ArrayList<Integer>()), true)),
ns, generateCoerce(generator, new TypeItem("Namespace")), ins(new FindPropertyStrictIns(), g.abc.constants.getMultinameId(new Multiname(Multiname.RTQNAME, g.abc.constants.getStringId(variableName, true), 0, 0, 0, new ArrayList<Integer>()), true)),
ns, generateCoerce(generator, new TypeItem("Namespace")), ins(new GetPropertyIns(), g.abc.constants.getMultinameId(new Multiname(Multiname.RTQNAME, g.abc.constants.getStringId(variableName, true), 0, 0, 0, new ArrayList<Integer>()), true)),
needsReturn ? null : ins(new PopIns()),
killTemp(localData, generator, Arrays.asList(ns_temp, index_temp, ret_temp))
);
@@ -292,7 +307,7 @@ public class NameAVM2Item extends AssignableAVM2Item {
if (slotNumber > -1) {
return toSourceMerge(localData, generator,
ins(new GetScopeObjectIns(), slotScope),
assignedValue, !(("" + assignedValue.returnType()).equals("" + type) && (basicTypes.contains("" + type))) ? generateCoerce(generator, "" + type) : null, needsReturn
assignedValue, !(("" + assignedValue.returnType()).equals("" + type) && (basicTypes.contains("" + type))) ? generateCoerce(generator, type) : null, needsReturn
? dupSetTemp(localData, generator, ret_temp) : null, generateSetLoc(regNumber), slotNumber > -1
? ins(new SetSlotIns(), slotNumber)
: null,
@@ -300,7 +315,7 @@ public class NameAVM2Item extends AssignableAVM2Item {
killTemp(localData, generator, Arrays.asList(ret_temp)));
} else {
return toSourceMerge(localData, generator, assignedValue, !(("" + assignedValue.returnType()).equals("" + type) && (basicTypes.contains("" + type))) ? generateCoerce(generator, "" + type) : null, needsReturn
return toSourceMerge(localData, generator, assignedValue, !(("" + assignedValue.returnType()).equals("" + type) && (basicTypes.contains("" + type))) ? generateCoerce(generator, type) : null, needsReturn
? ins(new DupIns()) : null, generateSetLoc(regNumber));
}
} else {
@@ -376,10 +391,10 @@ public class NameAVM2Item extends AssignableAVM2Item {
if (variableName == null && ns != null && index != null) {
return toSourceMerge(localData, generator,
ns, generateCoerce(generator, "Namespace"), index, ins(new ConvertSIns()),
ns, generateCoerce(generator, new TypeItem("Namespace")), index, ins(new ConvertSIns()),
ins(new FindPropertyStrictIns(), g.abc.constants.getMultinameId(new Multiname(Multiname.RTQNAMEL, 0, 0, 0, 0, new ArrayList<Integer>()), true)),
dupSetTemp(localData, generator, name_temp),
ns, generateCoerce(generator, "Namespace"),
ns, generateCoerce(generator, new TypeItem("Namespace")),
dupSetTemp(localData, generator, ns_temp),
//getTemp(localData, generator, ns_temp), generateCoerce(generator, "Namespace"), getTemp(localData, generator, index_temp), ins(new ConvertSIns()),
//Start get original
@@ -400,10 +415,10 @@ public class NameAVM2Item extends AssignableAVM2Item {
}
if (variableName != null && ns != null && index == null) {
return toSourceMerge(localData, generator,
ns, generateCoerce(generator, "Namespace"),
ns, generateCoerce(generator, new TypeItem("Namespace")),
ins(new FindPropertyStrictIns(), g.abc.constants.getMultinameId(new Multiname(Multiname.RTQNAME, g.abc.constants.getStringId(variableName, true), 0, 0, 0, new ArrayList<Integer>()), true)),
dupSetTemp(localData, generator, name_temp),
ns, generateCoerce(generator, "Namespace"),
ns, generateCoerce(generator, new TypeItem("Namespace")),
dupSetTemp(localData, generator, ns_temp),
//Start get original
//getTemp(localData, generator, ns_temp), generateCoerce(generator, "Namespace"), ins(new FindPropertyStrictIns(), g.abc.constants.getMultinameId(new Multiname(Multiname.RTQNAME, g.abc.constants.getStringId(variableName, true), 0, 0, 0, new ArrayList<Integer>()), true)),

View File

@@ -94,7 +94,24 @@ public class PropertyAVM2Item extends AssignableAVM2Item {
}
private void resolve(SourceGeneratorLocalData localData, Reference<String> objectType, Reference<String> propertyType, Reference<Integer> propertyIndex) {
String objType = object == null ? null : object.returnType().toString();
String objType = null;
String objSubType = null;
if(object != null){
GraphTargetItem oretType = object.returnType();
if(oretType instanceof UnresolvedAVM2Item){
UnresolvedAVM2Item ur=(UnresolvedAVM2Item)oretType;
oretType = ur.resolved;
}
if(oretType instanceof TypeItem){
TypeItem t=(TypeItem)oretType;
objType = t.fullTypeName;
if(!t.subtypes.isEmpty()){
objSubType = t.subtypes.get(0);
}
}else{
objType = oretType.toString();
}
}
String propType = "";
int propIndex = 0;
if (scopeStack.isEmpty()) { //Everything is multiname when with command
@@ -225,6 +242,17 @@ public class PropertyAVM2Item extends AssignableAVM2Item {
List<ABC> abcs = new ArrayList<>();
abcs.add(abc);
abcs.addAll(otherABCs);
if(objType.equals("__AS3__.vec.Vector")){
if("int".equals(objSubType)){
objType = "__AS3__.vec.Vector$int";
}else if("Number".equals(objSubType)){
objType = "__AS3__.vec.Vector$double";
}else if("uint".equals(objSubType)){
objType = "__AS3__.vec.Vector$uint";
}else{
objType = "__AS3__.vec.Vector$object";
}
}
loopa:
for (ABC a : abcs) {
for (InstanceInfo ii : a.instance_info) {

View File

@@ -38,6 +38,7 @@ 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 com.jpexs.helpers.Helper;
import java.util.ArrayList;
import java.util.List;
@@ -59,10 +60,11 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item {
private boolean mustBeType;
public List<String> importedClasses;
public List<GraphTargetItem> scopeStack = new ArrayList<GraphTargetItem>();
public List<String> subtypes;
@Override
public AssignableAVM2Item copy() {
UnresolvedAVM2Item c = new UnresolvedAVM2Item(importedClasses, mustBeType, type, line, name, assignedValue, openedNamespaces);
UnresolvedAVM2Item c = new UnresolvedAVM2Item(subtypes, importedClasses, mustBeType, type, line, name, assignedValue, openedNamespaces);
c.setNs(ns);
c.nsKind = nsKind;
c.setIndex(index);
@@ -152,7 +154,7 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item {
return name;
}
public UnresolvedAVM2Item(List<String> importedClasses, boolean mustBeType, GraphTargetItem type, int line, String name, GraphTargetItem storeValue, List<Integer> openedNamespaces) {
public UnresolvedAVM2Item(List<String> subtypes, List<String> importedClasses, boolean mustBeType, GraphTargetItem type, int line, String name, GraphTargetItem storeValue, List<Integer> openedNamespaces) {
super(storeValue);
this.name = name;
this.assignedValue = storeValue;
@@ -161,6 +163,7 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item {
this.openedNamespaces = openedNamespaces;
this.mustBeType = mustBeType;
this.importedClasses = importedClasses;
this.subtypes = subtypes;
}
public boolean isDefinition() {
@@ -342,6 +345,18 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item {
}
if (impName.equals(parts.get(0))) {
TypeItem ret = new TypeItem(imp);
for (String s : subtypes) {
if (!subtypes.isEmpty() && parts.size() > 1) {
continue;
}
UnresolvedAVM2Item su = new UnresolvedAVM2Item(new ArrayList<String>(), importedClasses, true, null, line, s, null, openedNamespaces);
su.resolve(paramTypes, paramNames, abc, otherAbcs, callStack, variables);
if (!(su.resolved instanceof TypeItem)) {
throw new CompilationException("Not a type", line);
}
TypeItem st = (TypeItem) su.resolved;
ret.subtypes.add(st.fullTypeName);
}
resolved = ret;
for (int i = 1; i < parts.size(); i++) {
resolved = new PropertyAVM2Item(resolved, parts.get(i), null, abc, otherAbcs, openedNamespaces, new ArrayList<MethodBody>());
@@ -360,18 +375,70 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item {
}
}
//Search for types in opened namespaces
//Search all fully qualitfied types
List<ABC> allAbcs = new ArrayList<>();
allAbcs.add(abc);
allAbcs.addAll(otherAbcs);
for (int i = 0; i < parts.size(); i++) {
String fname = Helper.joinStrings(parts.subList(0, i + 1), ".");
for (ABC a : allAbcs) {
for (int c = 0; c < a.instance_info.size(); c++) {
if (fname.equals(a.instance_info.get(c).getName(a.constants).getNameWithNamespace(a.constants))) {
if (!subtypes.isEmpty() && parts.size() > i + 1) {
continue;
}
TypeItem ret = new TypeItem(fname);
for (String s : subtypes) {
UnresolvedAVM2Item su = new UnresolvedAVM2Item(new ArrayList<String>(), importedClasses, true, null, line, s, null, openedNamespaces);
su.resolve(paramTypes, paramNames, abc, otherAbcs, callStack, variables);
if (!(su.resolved instanceof TypeItem)) {
throw new CompilationException("Not a type", line);
}
TypeItem st = (TypeItem) su.resolved;
ret.subtypes.add(st.fullTypeName);
}
resolved = ret;
for (int j = i + 1; j < parts.size(); j++) {
resolved = new PropertyAVM2Item(resolved, parts.get(j), null, abc, otherAbcs, openedNamespaces, new ArrayList<MethodBody>());
if (j == parts.size() - 1) {
((PropertyAVM2Item) resolved).index = index;
((PropertyAVM2Item) resolved).assignedValue = assignedValue;
}
}
if (parts.size() == i + 1 && index != null) {
throw new CompilationException("Types do not have indices", line);
}
if (parts.size() == i + 1 && assignedValue != null) {
throw new CompilationException("Cannot assign type", line);
}
return ret;
}
}
}
}
//Search for types in opened namespaces
for (int ni : openedNamespaces) {
Namespace ons = abc.constants.getNamespace(ni);
Namespace ons = abc.constants.getNamespace(ni);
for (ABC a : allAbcs) {
for (int c = 0; c < a.instance_info.size(); c++) {
if ((a == abc && a.instance_info.get(c).getName(a.constants).namespace_index == ni) || (ons.kind != Namespace.KIND_PRIVATE && a.instance_info.get(c).getName(a.constants).getNamespace(a.constants).hasName(ons.getName(abc.constants), a.constants))) {
String cname = a.instance_info.get(c).getName(a.constants).getName(a.constants, new ArrayList<String>());
if (cname.equals(parts.get(0))) {
if (parts.get(0).equals(cname)) {
if (!subtypes.isEmpty() && parts.size() > 1) {
continue;
}
TypeItem ret = new TypeItem(a.instance_info.get(c).getName(a.constants).getNameWithNamespace(a.constants));
for (String s : subtypes) {
UnresolvedAVM2Item su = new UnresolvedAVM2Item(new ArrayList<String>(), importedClasses, true, null, line, s, null, openedNamespaces);
su.resolve(paramTypes, paramNames, abc, otherAbcs, callStack, variables);
if (!(su.resolved instanceof TypeItem)) {
throw new CompilationException("Not a type", line);
}
TypeItem st = (TypeItem) su.resolved;
ret.subtypes.add(st.fullTypeName);
}
resolved = ret;
for (int i = 1; i < parts.size(); i++) {
resolved = new PropertyAVM2Item(resolved, parts.get(i), null, abc, otherAbcs, openedNamespaces, new ArrayList<MethodBody>());
@@ -413,6 +480,24 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item {
return ret;
}
if(!subtypes.isEmpty() && parts.size()==1 && parts.get(0).equals("Vector")){
TypeItem ret = new TypeItem("__AS3__.vec.Vector");
for (String s : subtypes) {
UnresolvedAVM2Item su = new UnresolvedAVM2Item(new ArrayList<String>(), importedClasses, true, null, line, s, null, openedNamespaces);
su.resolve(paramTypes, paramNames, abc, otherAbcs, callStack, variables);
if (!(su.resolved instanceof TypeItem)) {
throw new CompilationException("Not a type", line);
}
TypeItem st = (TypeItem) su.resolved;
ret.subtypes.add(st.fullTypeName);
}
resolved = ret;
return ret;
}
if(mustBeType){
throw new CompilationException("Not a type", line);
}
resolved = null;
GraphTargetItem ret = null;
for (int i = 0; i < parts.size(); i++) {

View File

@@ -105,7 +105,7 @@ Identifier = [:jletter:][:jletterdigit:]*
IdentifierNs = {Identifier} ":" {Identifier}
TypeNameSpec = ".<" {Identifier} ">"
TypeNameSpec = ".<"
/* XML */
XMLIdentifier = {Identifier} | {IdentifierNs}
@@ -280,7 +280,7 @@ SingleCharacter = [^\r\n\'\\]
{LineTerminator} { yyline++;}
/* whitespace */
{WhiteSpace} { /*ignore*/ }
{TypeNameSpec} { String t=yytext(); return new ParsedSymbol(SymbolGroup.TYPENAME,SymbolType.TYPENAME,t.substring(2,t.length()-1)); }
{TypeNameSpec} { return new ParsedSymbol(SymbolGroup.TYPENAME,SymbolType.TYPENAME,yytext()); }
{XMLBeginOneTag} {string.setLength(0);
yybegin(XML);
String s=yytext();

View File

@@ -1,6 +1,6 @@
TODO List for AS3 parser/compiler:
------------------------------
- E4X (XML)
- typenames (Vectors)
- default xml namespace
- custom namespace modifiers
- custom namespace modifiers
- fix setproperty, getproperty stats calculation (stack pos)

View File

@@ -220,6 +220,7 @@ public class MethodBody implements Cloneable, Serializable {
}
public boolean autoFillStats(ABC abc, int initScope) {
//System.out.println("--------------");
CodeStats stats = code.getStats(abc, this, initScope);
if (stats == null) {
return false;

View File

@@ -23,7 +23,9 @@ import com.jpexs.decompiler.flash.abc.types.Namespace;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.graph.model.LocalData;
import com.jpexs.decompiler.graph.model.UnboundedTypeItem;
import com.jpexs.helpers.Helper;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
@@ -38,10 +40,16 @@ public class TypeItem extends GraphTargetItem {
public static UnboundedTypeItem UNBOUNDED = new UnboundedTypeItem();
public String fullTypeName;
public List<String> subtypes = new ArrayList<>();
public TypeItem(String fullTypeName) {
public TypeItem(String fullTypeName){
this(fullTypeName,new ArrayList<String>());
}
public TypeItem(String fullTypeName,List<String> subtypes) {
super(null, NOPRECEDENCE);
this.fullTypeName = fullTypeName;
this.subtypes.addAll(subtypes);
}
@Override
@@ -84,12 +92,20 @@ public class TypeItem extends GraphTargetItem {
@Override
public String toString() {
return fullTypeName;
String add="";
if(!subtypes.isEmpty()){
add+=".<";
add+=Helper.joinStrings(subtypes, ",");
add+=">";
}
return fullTypeName+add;
}
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);
@@ -98,7 +114,8 @@ public class TypeItem extends GraphTargetItem {
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)) {
return ii.name_index;
name_index = ii.name_index;
break;
}
}
}
@@ -106,11 +123,22 @@ public class TypeItem extends GraphTargetItem {
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))) {
return i;
name_index = i;
break;
}
}
}
return 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(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);
}
}