From b48fcf3c948e1e4b75d9434a481f78ea7157d717 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=F8=EDk?= Date: Sun, 20 Apr 2014 08:17:54 +0200 Subject: [PATCH] AS3 direct editation - as, is, const/var initializers, various bugfixes --- .../avm2/model/operations/AsTypeAVM2Item.java | 6 +- .../avm2/model/operations/IsTypeAVM2Item.java | 3 +- .../parser/script/AVM2SourceGenerator.java | 36 +- .../parser/script/ActionScriptParser.java | 479 +++++++++--------- .../parser/script/UnresolvedAVM2Item.java | 2 +- .../flash/abc/types/MethodBody.java | 8 + .../decompiler/flash/abc/types/Multiname.java | 2 +- 7 files changed, 284 insertions(+), 252 deletions(-) diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/AsTypeAVM2Item.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/AsTypeAVM2Item.java index 5aa8501e4..5fb55acb8 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/AsTypeAVM2Item.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/AsTypeAVM2Item.java @@ -19,6 +19,7 @@ package com.jpexs.decompiler.flash.abc.avm2.model.operations; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; import com.jpexs.decompiler.flash.abc.avm2.instructions.types.AsTypeIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.types.AsTypeLateIns; import com.jpexs.decompiler.graph.CompilationException; import com.jpexs.decompiler.graph.GraphSourceItem; import com.jpexs.decompiler.graph.GraphTargetItem; @@ -35,13 +36,12 @@ public class AsTypeAVM2Item extends BinaryOpItem { @Override public List toSource(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { return toSourceMerge(localData, generator, leftSide, rightSide, - new AVM2Instruction(0, new AsTypeIns(), new int[]{}, new byte[0]) + new AVM2Instruction(0, new AsTypeLateIns(), new int[]{}, new byte[0]) ); } @Override public GraphTargetItem returnType() { return rightSide; - } - + } } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/IsTypeAVM2Item.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/IsTypeAVM2Item.java index b4e2764b1..92d802dfa 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/IsTypeAVM2Item.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/IsTypeAVM2Item.java @@ -19,6 +19,7 @@ package com.jpexs.decompiler.flash.abc.avm2.model.operations; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; import com.jpexs.decompiler.flash.abc.avm2.instructions.types.IsTypeIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.types.IsTypeLateIns; import com.jpexs.decompiler.graph.CompilationException; import com.jpexs.decompiler.graph.GraphSourceItem; import com.jpexs.decompiler.graph.GraphTargetItem; @@ -36,7 +37,7 @@ public class IsTypeAVM2Item extends BinaryOpItem { @Override public List toSource(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { return toSourceMerge(localData, generator, leftSide, rightSide, - new AVM2Instruction(0, new IsTypeIns(), new int[]{}, new byte[0]) + new AVM2Instruction(0, new IsTypeLateIns(), new int[]{}, new byte[0]) ); } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java index f8cff906c..ba783b27a 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java @@ -1167,24 +1167,33 @@ public class AVM2SourceGenerator implements SourceGenerator { 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); + int init = 0; if (constructor == null) { - instanceInfo.iinit_index = method(new ArrayList(), pkg.packageName, false, new ArrayList(), initScope + 1, false, 0, name, extendsVal != null ? extendsVal.toString() : null, true, localData, new ArrayList(), new ArrayList(), new ArrayList(), new ArrayList(), TypeItem.UNBOUNDED/*?? FIXME*/); + instanceInfo.iinit_index = init = method(new ArrayList(), pkg.packageName, false, new ArrayList(), initScope + 1, false, 0, name, extendsVal != null ? extendsVal.toString() : null, true, localData, new ArrayList(), new ArrayList(), new ArrayList(), new ArrayList(), TypeItem.UNBOUNDED/*?? FIXME*/); } else { MethodAVM2Item m = (MethodAVM2Item) constructor; - instanceInfo.iinit_index = method(new ArrayList(), pkg.packageName, m.needsActivation, m.subvariables, initScope + 1, m.hasRest, m.line, name, extendsVal != null ? extendsVal.toString() : null, true, localData, m.paramTypes, m.paramNames, m.paramValues, m.body, TypeItem.UNBOUNDED/*?? FIXME*/); + instanceInfo.iinit_index = init = method(new ArrayList(), pkg.packageName, m.needsActivation, m.subvariables, initScope + 1, m.hasRest, m.line, name, extendsVal != null ? extendsVal.toString() : null, true, localData, m.paramTypes, m.paramNames, m.paramValues, m.body, TypeItem.UNBOUNDED/*?? FIXME*/); } //Class initializer int staticMi = method(new ArrayList(), pkg.packageName, staticNeedsActivation, sinitVariables, initScope, false,0, name, superName, false, localData, new ArrayList(),new ArrayList(),new ArrayList(), staticInit, TypeItem.UNBOUNDED); - MethodBody mb=abc.findBody(staticMi); + MethodBody sinitBody=abc.findBody(staticMi); - /*List initcode = new ArrayList<>(); + List sinitcode = new ArrayList<>(); + List initcode = new ArrayList<>(); for (GraphTargetItem ti : traitItems) { if (ti instanceof SlotAVM2Item) { SlotAVM2Item si = (SlotAVM2Item) ti; - if (si.isStatic()) { + if (si.isStatic() && si.value!=null) { + sinitcode.add(ins(new FindPropertyStrictIns(), traitName(namespace, si.var))); + List tis = new ArrayList<>(); + tis.add(si.value); + sinitcode.addAll(toInsList(generate(localData, tis))); + sinitcode.add(ins(new InitPropertyIns(), traitName(namespace, si.var))); + } + if (!si.isStatic() && si.value!=null) { initcode.add(ins(new FindPropertyStrictIns(), traitName(namespace, si.var))); List tis = new ArrayList<>(); tis.add(si.value); @@ -1193,11 +1202,17 @@ public class AVM2SourceGenerator implements SourceGenerator { } } } - if(mb.code.code.get(mb.code.code.size()-1).definition instanceof ReturnVoidIns){ - mb.code.code.addAll(mb.code.code.size()-1,initcode); + + MethodBody initBody=abc.findBody(init); + if(initBody.code.code.get(initBody.code.code.size()-1).definition instanceof ReturnVoidIns){ + initBody.code.code.addAll(initBody.code.code.size()-1,initcode); } - mb.autoFillStats(abc, initScope);*/ - + + if(sinitBody.code.code.get(sinitBody.code.code.size()-1).definition instanceof ReturnVoidIns){ + sinitBody.code.code.addAll(sinitBody.code.code.size()-1,sinitcode); + } + sinitBody.markOffsets(); + sinitBody.autoFillStats(abc, initScope); classInfo.cinit_index = staticMi; instanceInfo.interfaces = new int[implementsStr.size()]; @@ -1668,11 +1683,14 @@ public class AVM2SourceGenerator implements SourceGenerator { offset += ins.getBytes().length; } + mbody.markOffsets(); mbody.autoFillStats(abc, initScope); abc.addMethodBody(mbody); return mbody.method_info; } + + public ValueKind getValueKind(int nsKind, GraphTargetItem type, GraphTargetItem val) { diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScriptParser.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScriptParser.java index 81cb98d98..0ca6083c7 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScriptParser.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScriptParser.java @@ -51,6 +51,7 @@ 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; import com.jpexs.decompiler.flash.abc.avm2.model.operations.AddAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.operations.AsTypeAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.operations.BitAndAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.operations.BitOrAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.operations.BitXorAVM2Item; @@ -60,6 +61,7 @@ import com.jpexs.decompiler.flash.abc.avm2.model.operations.EqAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.operations.GeAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.operations.GtAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.operations.InstanceOfAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.operations.IsTypeAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.operations.LShiftAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.operations.LeAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.operations.LtAVM2Item; @@ -456,11 +458,11 @@ public class ActionScriptParser { return new FunctionAVM2Item(needsActivation2.getVal(), namespace, hasRest, line, functionName, paramTypes, paramNames, paramValues, body, subvariables, retType); } - private GraphTargetItem traits(List sinitVariables,Reference sinitNeedsActivation,List staticInitializer, List importedClasses, int privateNs, int protectedNs, int publicNs, int packageInternalNs, int protectedStaticNs, List openedNamespaces, String packageName, String classNameStr, boolean isInterface, List traits) throws ParseException, IOException, CompilationException { + private GraphTargetItem traits(List sinitVariables, Reference sinitNeedsActivation, List staticInitializer, List importedClasses, int privateNs, int protectedNs, int publicNs, int packageInternalNs, int protectedStaticNs, List openedNamespaces, String packageName, String classNameStr, boolean isInterface, List traits) throws ParseException, IOException, CompilationException { ParsedSymbol s; GraphTargetItem constr = null; - List variables = new ArrayList<>(); TypeItem thisType = new TypeItem("".equals(packageName) ? classNameStr : packageName + "." + classNameStr); + List constrVariables = new ArrayList<>(); looptrait: while (true) { s = lex(); @@ -472,14 +474,13 @@ public class ActionScriptParser { boolean isFinal = false; boolean isDynamic = false; String customAccess = null; - - - if(s.type == SymbolType.CURLY_OPEN){ + + if (s.type == SymbolType.CURLY_OPEN) { staticInitializer.addAll(commands(sinitNeedsActivation, importedClasses, openedNamespaces, new Stack(), new HashMap(), new HashMap(), true, false, 0, sinitVariables)); expectedType(SymbolType.CURLY_CLOSE); s = lex(); } - + //TODO: final, dynamic while (s.isType(SymbolType.STATIC, SymbolType.PUBLIC, SymbolType.PRIVATE, SymbolType.PROTECTED, SymbolType.OVERRIDE, SymbolType.FINAL, SymbolType.DYNAMIC, SymbolType.IDENTIFIER)) { if (s.type == SymbolType.FINAL) { @@ -551,13 +552,13 @@ public class ActionScriptParser { GraphTargetItem extendsTypeStr = null; s = lex(); if (s.type == SymbolType.EXTENDS) { - extendsTypeStr = type(new Reference(false), importedClasses, openedNamespaces, variables); + extendsTypeStr = type(new Reference(false), importedClasses, openedNamespaces, new ArrayList()); s = lex(); } List implementsTypeStrs = new ArrayList<>(); if (s.type == SymbolType.IMPLEMENTS) { do { - GraphTargetItem implementsTypeStr = type(new Reference(false), importedClasses, openedNamespaces, variables); + GraphTargetItem implementsTypeStr = type(new Reference(false), importedClasses, openedNamespaces, new ArrayList()); implementsTypeStrs.add(implementsTypeStr); s = lex(); } while (s.type == SymbolType.COMMA); @@ -566,7 +567,7 @@ public class ActionScriptParser { if (customAccess != null) { throw new ParseException("Class cannot have custom namespace", lexer.yyline()); } - traits.add((classTraits(packageInternalNs, importedClasses, privateNs, isDynamic, isFinal, openedNamespaces, packageName, namespace, false, classTypeStr, extendsTypeStr, implementsTypeStrs, variables))); + traits.add((classTraits(packageInternalNs, importedClasses, privateNs, isDynamic, isFinal, openedNamespaces, packageName, namespace, false, classTypeStr, extendsTypeStr, implementsTypeStrs, new ArrayList()))); expectedType(SymbolType.CURLY_CLOSE); break; case INTERFACE: @@ -591,7 +592,7 @@ public class ActionScriptParser { if (s.type == SymbolType.EXTENDS) { do { - GraphTargetItem intExtendsTypeStr = type(new Reference(false), importedClasses, openedNamespaces, variables); + GraphTargetItem intExtendsTypeStr = type(new Reference(false), importedClasses, openedNamespaces, new ArrayList()); intExtendsTypeStrs.add(intExtendsTypeStr); s = lex(); } while (s.type == SymbolType.COMMA); @@ -600,7 +601,7 @@ public class ActionScriptParser { if (customAccess != null) { throw new ParseException("Interface cannot have custom namespace", lexer.yyline()); } - traits.add((classTraits(packageInternalNs, importedClasses, privateNs, false, isFinal, openedNamespaces, packageName, namespace, true, intTypeStr, null, intExtendsTypeStrs, variables))); + traits.add((classTraits(packageInternalNs, importedClasses, privateNs, false, isFinal, openedNamespaces, packageName, namespace, true, intTypeStr, null, intExtendsTypeStrs, new ArrayList()))); expectedType(SymbolType.CURLY_CLOSE); break; @@ -639,17 +640,17 @@ public class ActionScriptParser { if (isFinal) { throw new ParseException("Final flag not allowed for constructor", lexer.yyline()); } - constr = (method(customAccess, new Reference(false), importedClasses, false, false, thisType, openedNamespaces, false, namespace, !isInterface, "", true, variables)); + constr = (method(customAccess, new Reference(false), importedClasses, false, false, thisType, openedNamespaces, false, namespace, !isInterface, "", true, constrVariables)); } else { if (isStatic) { GraphTargetItem t; - MethodAVM2Item ft = method(customAccess, new Reference(false), importedClasses, isOverride, isFinal, thisType, openedNamespaces, isStatic, namespace, !isInterface, fname, true, variables); + MethodAVM2Item ft = method(customAccess, new Reference(false), importedClasses, isOverride, isFinal, thisType, openedNamespaces, isStatic, namespace, !isInterface, fname, true, new ArrayList()); traits.add(ft); if (isGetter || isSetter) { throw new ParseException("Getter or Setter cannot be static", lexer.yyline()); } } else { - MethodAVM2Item ft = method(customAccess, new Reference(false), importedClasses, isOverride, isFinal, thisType, openedNamespaces, isStatic, namespace, !isInterface, fname, true, variables); + MethodAVM2Item ft = method(customAccess, new Reference(false), importedClasses, isOverride, isFinal, thisType, openedNamespaces, isStatic, namespace, !isInterface, fname, true, new ArrayList()); GraphTargetItem t; if (isGetter) { if (!ft.paramTypes.isEmpty()) { @@ -713,14 +714,14 @@ public class ActionScriptParser { s = lex(); GraphTargetItem type = null; if (s.type == SymbolType.COLON) { - type = type(new Reference(false), importedClasses, openedNamespaces, variables); + type = type(new Reference(false), importedClasses, openedNamespaces, new ArrayList()); s = lex(); } GraphTargetItem value = null; if (s.type == SymbolType.ASSIGN) { - value = expression(new Reference(false), importedClasses, openedNamespaces, new HashMap(), false, false, true, variables); + value = expression(new Reference(false), importedClasses, openedNamespaces, new HashMap(), false, false, true, isStatic||isConst?sinitVariables:constrVariables); s = lex(); } GraphTargetItem tar; @@ -777,12 +778,12 @@ public class ActionScriptParser { Reference staticNeedsActivation = new Reference<>(false); List staticInit = new ArrayList<>(); List sinitVariables = new ArrayList<>(); - GraphTargetItem constr = traits(sinitVariables,staticNeedsActivation,staticInit,importedClasses, privateNs, protectedNs, publicNs, packageInternalNs, protectedStaticNs, openedNamespaces, packageName, classNameStr, isInterface, traits); + GraphTargetItem constr = traits(sinitVariables, staticNeedsActivation, staticInit, importedClasses, privateNs, protectedNs, publicNs, packageInternalNs, protectedStaticNs, openedNamespaces, packageName, classNameStr, isInterface, traits); if (isInterface) { return new InterfaceAVM2Item(openedNamespaces, isFinal, namespace, classNameStr, implementsStr, traits); } else { - return new ClassAVM2Item(openedNamespaces, protectedNs, isDynamic, isFinal, namespace, classNameStr, extendsStr, implementsStr, staticInit,staticNeedsActivation.getVal(),sinitVariables,constr, traits); + return new ClassAVM2Item(openedNamespaces, protectedNs, isDynamic, isFinal, namespace, classNameStr, extendsStr, implementsStr, staticInit, staticNeedsActivation.getVal(), sinitVariables, constr, traits); } } @@ -1362,7 +1363,7 @@ public class ActionScriptParser { lexer.pushback(s); for (int i = loops.size() - 1; i >= 0; i--) { if (loops.get(i).id >= 0) {//no switches - cloopId = loops.peek().id; + cloopId = loops.get(i).id; break; } } @@ -1527,223 +1528,228 @@ public class ActionScriptParser { private GraphTargetItem expressionRemainder(Reference needsActivation, List openedNamespaces, GraphTargetItem expr, HashMap registerVars, boolean inFunction, boolean inMethod, boolean allowRemainder, List variables, List importedClasses) throws IOException, ParseException { GraphTargetItem ret = null; ParsedSymbol s = lex(); - switch (s.type) { - case DESCENDANTS: - ParsedSymbol d = lex(); - expected(d, lexer.yyline(), SymbolType.IDENTIFIER); - ret = new GetDescendantsAVM2Item(expr, d.value.toString(), openedNamespaces); - allowRemainder = true; - break; - case FILTER: - needsActivation.setVal(true); - ret = new XMLFilterAVM2Item(expr, expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables), openedNamespaces); - expectedType(SymbolType.PARENT_CLOSE); - allowRemainder = true; - break; - /*case NAMESPACE_OP: - s = lex(); - if (s.type == SymbolType.BRACKET_OPEN) { - GraphTargetItem index = expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables); - NameAVM2Item name = new NameAVM2Item(new UnboundedTypeItem(), lexer.yyline(), null, null, false, openedNamespaces); - name.setIndex(index); - name.setNs(expr); - ret = name; - expectedType(SymbolType.BRACKET_CLOSE); - } else { - lexer.pushback(s); - GraphTargetItem name = name(needsActivation, false, openedNamespaces, registerVars, inFunction, inMethod, variables, importedClasses); - if (name instanceof UnresolvedAVM2Item) { - ((UnresolvedAVM2Item) name).setNs(expr); - //((UnresolvedAVM2Item) name).unresolved = false; - //TODO - } else { - throw new ParseException("Not a property name", lexer.yyline()); - } - ret = name; - } - break;*/ - case IN: - ret = new InAVM2Item(null, expr, expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables)); - break; - case TERNAR: - GraphTargetItem terOnTrue = expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables); - expectedType(SymbolType.COLON); - GraphTargetItem terOnFalse = expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables); - ret = new TernarOpItem(null, expr, terOnTrue, terOnFalse); - break; - case SHIFT_LEFT: - ret = new LShiftAVM2Item(null, expr, expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, false, variables)); - break; - case SHIFT_RIGHT: - ret = new RShiftAVM2Item(null, expr, expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, false, variables)); - break; - case USHIFT_RIGHT: - ret = new URShiftAVM2Item(null, expr, expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, false, variables)); - break; - case BITAND: - ret = new BitAndAVM2Item(null, expr, expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, false, variables)); - break; - case BITOR: - ret = new BitOrAVM2Item(null, expr, expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, false, variables)); - break; - case DIVIDE: - ret = new DivideAVM2Item(null, expr, expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, false, variables)); - break; - case MODULO: - ret = new ModuloAVM2Item(null, expr, expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, false, variables)); - break; - case EQUALS: - ret = new EqAVM2Item(null, expr, expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, false, variables)); - break; - case STRICT_EQUALS: - ret = new StrictEqAVM2Item(null, expr, expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, false, variables)); - break; - case NOT_EQUAL: - ret = new NeqAVM2Item(null, expr, expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, false, variables)); - break; - case STRICT_NOT_EQUAL: - ret = new StrictNeqAVM2Item(null, expr, expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, false, variables)); - break; - case LOWER_THAN: - ret = new LtAVM2Item(null, expr, expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, false, variables)); - break; - case LOWER_EQUAL: - ret = new LeAVM2Item(null, expr, expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, false, variables)); - break; - case GREATER_THAN: - case XML_STARTVARTAG_BEGIN: - case XML_STARTTAG_BEGIN: - if (s.type != SymbolType.GREATER_THAN) { - lexer.yypushbackstr(s.value.toString().substring(1)); //parse again as GREATER_THAN - } - ret = new GtAVM2Item(null, expr, expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, false, variables)); - break; - case GREATER_EQUAL: - ret = new GeAVM2Item(null, expr, expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, false, variables)); - break; - case AND: - ret = new AndItem(null, expr, expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, false, variables)); - break; - case OR: - ret = new OrItem(null, expr, expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, false, variables)); - break; - case MINUS: - ret = new SubtractAVM2Item(null, expr, expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, false, variables)); - break; - case MULTIPLY: - ret = new MultiplyAVM2Item(null, expr, expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, false, variables)); - break; - case PLUS: - ret = new AddAVM2Item(null, expr, expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, false, variables)); - break; - case XOR: - ret = new BitXorAVM2Item(null, expr, expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, false, variables)); - break; - case AS: - //TODO - break; - case INSTANCEOF: - ret = new InstanceOfAVM2Item(null, expr, expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, false, variables)); - break; - case IS: + + if (ret == null) { + switch (s.type) { + case AS: + GraphTargetItem type = type(needsActivation, importedClasses, openedNamespaces, variables); + ret = new AsTypeAVM2Item(null, expr, type); + allowRemainder = false; + break; + case DESCENDANTS: + ParsedSymbol d = lex(); + expected(d, lexer.yyline(), SymbolType.IDENTIFIER); + ret = new GetDescendantsAVM2Item(expr, d.value.toString(), openedNamespaces); + allowRemainder = true; + break; + case FILTER: + needsActivation.setVal(true); + ret = new XMLFilterAVM2Item(expr, expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables), openedNamespaces); + expectedType(SymbolType.PARENT_CLOSE); + allowRemainder = true; + break; + /*case NAMESPACE_OP: + s = lex(); + if (s.type == SymbolType.BRACKET_OPEN) { + GraphTargetItem index = expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables); + NameAVM2Item name = new NameAVM2Item(new UnboundedTypeItem(), lexer.yyline(), null, null, false, openedNamespaces); + name.setIndex(index); + name.setNs(expr); + ret = name; + expectedType(SymbolType.BRACKET_CLOSE); + } else { + lexer.pushback(s); + GraphTargetItem name = name(needsActivation, false, openedNamespaces, registerVars, inFunction, inMethod, variables, importedClasses); + if (name instanceof UnresolvedAVM2Item) { + ((UnresolvedAVM2Item) name).setNs(expr); + //((UnresolvedAVM2Item) name).unresolved = false; + //TODO + } else { + throw new ParseException("Not a property name", lexer.yyline()); + } + ret = name; + } + break;*/ + case IN: + ret = new InAVM2Item(null, expr, expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables)); + break; + case TERNAR: + GraphTargetItem terOnTrue = expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables); + expectedType(SymbolType.COLON); + GraphTargetItem terOnFalse = expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables); + ret = new TernarOpItem(null, expr, terOnTrue, terOnFalse); + break; + case SHIFT_LEFT: + ret = new LShiftAVM2Item(null, expr, expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, false, variables)); + break; + case SHIFT_RIGHT: + ret = new RShiftAVM2Item(null, expr, expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, false, variables)); + break; + case USHIFT_RIGHT: + ret = new URShiftAVM2Item(null, expr, expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, false, variables)); + break; + case BITAND: + ret = new BitAndAVM2Item(null, expr, expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, false, variables)); + break; + case BITOR: + ret = new BitOrAVM2Item(null, expr, expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, false, variables)); + break; + case DIVIDE: + ret = new DivideAVM2Item(null, expr, expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, false, variables)); + break; + case MODULO: + ret = new ModuloAVM2Item(null, expr, expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, false, variables)); + break; + case EQUALS: + ret = new EqAVM2Item(null, expr, expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, false, variables)); + break; + case STRICT_EQUALS: + ret = new StrictEqAVM2Item(null, expr, expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, false, variables)); + break; + case NOT_EQUAL: + ret = new NeqAVM2Item(null, expr, expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, false, variables)); + break; + case STRICT_NOT_EQUAL: + ret = new StrictNeqAVM2Item(null, expr, expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, false, variables)); + break; + case LOWER_THAN: + ret = new LtAVM2Item(null, expr, expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, false, variables)); + break; + case LOWER_EQUAL: + ret = new LeAVM2Item(null, expr, expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, false, variables)); + break; + case GREATER_THAN: + case XML_STARTVARTAG_BEGIN: + case XML_STARTTAG_BEGIN: + if (s.type != SymbolType.GREATER_THAN) { + lexer.yypushbackstr(s.value.toString().substring(1)); //parse again as GREATER_THAN + } + ret = new GtAVM2Item(null, expr, expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, false, variables)); + break; + case GREATER_EQUAL: + ret = new GeAVM2Item(null, expr, expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, false, variables)); + break; + case AND: + ret = new AndItem(null, expr, expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, false, variables)); + break; + case OR: + ret = new OrItem(null, expr, expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, false, variables)); + break; + case MINUS: + ret = new SubtractAVM2Item(null, expr, expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, false, variables)); + break; + case MULTIPLY: + ret = new MultiplyAVM2Item(null, expr, expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, false, variables)); + break; + case PLUS: + ret = new AddAVM2Item(null, expr, expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, false, variables)); + break; + case XOR: + ret = new BitXorAVM2Item(null, expr, expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, false, variables)); + break; + case INSTANCEOF: + ret = new InstanceOfAVM2Item(null, expr, expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, false, variables)); + break; + case IS: + GraphTargetItem istype = type(needsActivation, importedClasses, openedNamespaces, variables); + ret = new IsTypeAVM2Item(null, expr, istype); + allowRemainder = false; + break; + case ASSIGN: + case ASSIGN_BITAND: + case ASSIGN_BITOR: + case ASSIGN_DIVIDE: + case ASSIGN_MINUS: + case ASSIGN_MODULO: + case ASSIGN_MULTIPLY: + case ASSIGN_PLUS: + case ASSIGN_SHIFT_LEFT: + case ASSIGN_SHIFT_RIGHT: + case ASSIGN_USHIFT_RIGHT: + case ASSIGN_XOR: + GraphTargetItem assigned = expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables); + switch (s.type) { + case ASSIGN: + //assigned = assigned; + break; + case ASSIGN_BITAND: + assigned = new BitAndAVM2Item(null, expr, assigned); + break; + case ASSIGN_BITOR: + assigned = new BitOrAVM2Item(null, expr, assigned); + break; + case ASSIGN_DIVIDE: + assigned = new DivideAVM2Item(null, expr, assigned); + break; + case ASSIGN_MINUS: + assigned = new SubtractAVM2Item(null, expr, assigned); + break; + case ASSIGN_MODULO: + assigned = new ModuloAVM2Item(null, expr, assigned); + break; + case ASSIGN_MULTIPLY: + assigned = new MultiplyAVM2Item(null, expr, assigned); + break; + case ASSIGN_PLUS: + assigned = new AddAVM2Item(null, expr, assigned); + break; + case ASSIGN_SHIFT_LEFT: + assigned = new LShiftAVM2Item(null, expr, assigned); + break; + case ASSIGN_SHIFT_RIGHT: + assigned = new RShiftAVM2Item(null, expr, assigned); + break; + case ASSIGN_USHIFT_RIGHT: + assigned = new URShiftAVM2Item(null, expr, assigned); + break; + case ASSIGN_XOR: + assigned = new BitXorAVM2Item(null, expr, assigned); + break; + } - break; + if (!(expr instanceof AssignableAVM2Item)) { + throw new ParseException("Invalid assignment", lexer.yyline()); + } + AssignableAVM2Item as = ((AssignableAVM2Item) expr).copy(); + if ((as instanceof UnresolvedAVM2Item) || (as instanceof NameAVM2Item)) { + variables.add(as); + } + as.setAssignedValue(assigned); + if (expr instanceof NameAVM2Item) { + ((NameAVM2Item) expr).setDefinition(false); + } + ret = as; + break; + case INCREMENT: //postincrement + if (!(expr instanceof AssignableAVM2Item)) { + throw new ParseException("Invalid assignment", lexer.yyline()); + } + ret = new PostIncrementAVM2Item(null, expr); + break; + case DECREMENT: //postdecrement + if (!(expr instanceof AssignableAVM2Item)) { + throw new ParseException("Invalid assignment", lexer.yyline()); + } + ret = new PostDecrementAVM2Item(null, expr); + break; + case DOT: //member + case BRACKET_OPEN: //member + case PARENT_OPEN: //function call + lexer.pushback(s); + ret = memberOrCall(needsActivation, importedClasses, openedNamespaces, expr, registerVars, inFunction, inMethod, variables); + break; - case ASSIGN: - case ASSIGN_BITAND: - case ASSIGN_BITOR: - case ASSIGN_DIVIDE: - case ASSIGN_MINUS: - case ASSIGN_MODULO: - case ASSIGN_MULTIPLY: - case ASSIGN_PLUS: - case ASSIGN_SHIFT_LEFT: - case ASSIGN_SHIFT_RIGHT: - case ASSIGN_USHIFT_RIGHT: - case ASSIGN_XOR: - GraphTargetItem assigned = expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables); - switch (s.type) { - case ASSIGN: - //assigned = assigned; - break; - case ASSIGN_BITAND: - assigned = new BitAndAVM2Item(null, expr, assigned); - break; - case ASSIGN_BITOR: - assigned = new BitOrAVM2Item(null, expr, assigned); - break; - case ASSIGN_DIVIDE: - assigned = new DivideAVM2Item(null, expr, assigned); - break; - case ASSIGN_MINUS: - assigned = new SubtractAVM2Item(null, expr, assigned); - break; - case ASSIGN_MODULO: - assigned = new ModuloAVM2Item(null, expr, assigned); - break; - case ASSIGN_MULTIPLY: - assigned = new MultiplyAVM2Item(null, expr, assigned); - break; - case ASSIGN_PLUS: - assigned = new AddAVM2Item(null, expr, assigned); - break; - case ASSIGN_SHIFT_LEFT: - assigned = new LShiftAVM2Item(null, expr, assigned); - break; - case ASSIGN_SHIFT_RIGHT: - assigned = new RShiftAVM2Item(null, expr, assigned); - break; - case ASSIGN_USHIFT_RIGHT: - assigned = new URShiftAVM2Item(null, expr, assigned); - break; - case ASSIGN_XOR: - assigned = new BitXorAVM2Item(null, expr, assigned); - break; - } - - if (!(expr instanceof AssignableAVM2Item)) { - throw new ParseException("Invalid assignment", lexer.yyline()); - } - AssignableAVM2Item as = ((AssignableAVM2Item) expr).copy(); - if ((as instanceof UnresolvedAVM2Item) || (as instanceof NameAVM2Item)) { - variables.add(as); - } - as.setAssignedValue(assigned); - if (expr instanceof NameAVM2Item) { - ((NameAVM2Item) expr).setDefinition(false); - } - ret = as; - break; - case INCREMENT: //postincrement - if (!(expr instanceof AssignableAVM2Item)) { - throw new ParseException("Invalid assignment", lexer.yyline()); - } - ret = new PostIncrementAVM2Item(null, expr); - break; - case DECREMENT: //postdecrement - if (!(expr instanceof AssignableAVM2Item)) { - throw new ParseException("Invalid assignment", lexer.yyline()); - } - ret = new PostDecrementAVM2Item(null, expr); - break; - case DOT: //member - case BRACKET_OPEN: //member - case PARENT_OPEN: //function call - lexer.pushback(s); - ret = memberOrCall(needsActivation, importedClasses, openedNamespaces, expr, registerVars, inFunction, inMethod, variables); - break; - - default: - lexer.pushback(s); - if (expr instanceof ParenthesisItem) { - if (isType(((ParenthesisItem) expr).value)) { - GraphTargetItem expr2 = expression(needsActivation, importedClasses, openedNamespaces, false, registerVars, inFunction, inMethod, true, variables); - if (expr2 != null) { - ret = new CoerceAVM2Item(null, ((ParenthesisItem) expr).value, expr2); + default: + lexer.pushback(s); + if (expr instanceof ParenthesisItem) { + if (isType(((ParenthesisItem) expr).value)) { + GraphTargetItem expr2 = expression(needsActivation, importedClasses, openedNamespaces, false, registerVars, inFunction, inMethod, true, variables); + if (expr2 != null) { + ret = new CoerceAVM2Item(null, ((ParenthesisItem) expr).value, expr2); + } } } - } - + } } ret = fixPrecedence(ret); return ret; @@ -1954,7 +1960,7 @@ public class ActionScriptParser { break; case INCREMENT: case DECREMENT: //preincrement - GraphTargetItem varincdec = expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables);//name(false, openedNamespaces, registerVars, inFunction, inMethod, variables); + GraphTargetItem varincdec = expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, false/*?*/, variables);//name(false, openedNamespaces, registerVars, inFunction, inMethod, variables); if (!isNameOrProp(varincdec)) { throw new ParseException("Not a property or name", lexer.yyline()); } @@ -2103,7 +2109,7 @@ public class ActionScriptParser { } lexer.pushback(s); - traits(new ArrayList(),new Reference(false),new ArrayList(),importedClasses, privateNs, 0, publicNs, packageInternalNs, 0, openedNamespaces, name, null, false, items); + traits(new ArrayList(), new Reference(false), new ArrayList(), importedClasses, privateNs, 0, publicNs, packageInternalNs, 0, openedNamespaces, name, null, false, items); expectedType(SymbolType.CURLY_CLOSE); return new PackageAVM2Item(name, items); } @@ -2143,8 +2149,7 @@ public class ActionScriptParser { this.otherABCs = otherABCs; } - - public static void compile(String src, ABC abc, boolean documentClass,String fileName) throws ParseException, IOException, InterruptedException, CompilationException { + public static void compile(String src, ABC abc, boolean documentClass, String fileName) throws ParseException, IOException, InterruptedException, CompilationException { SWC swc = new SWC(new FileInputStream(Configuration.getPlayerSWC())); SWF swf = new SWF(swc.getSWF("library.swf"), true); List playerABCs = new ArrayList<>(); @@ -2156,7 +2161,7 @@ public class ActionScriptParser { ActionScriptParser parser = new ActionScriptParser(abc, playerABCs); parser.addScript(src, documentClass, fileName); } - + public static void compile(String src, String dst) { System.err.println("WARNING: AS3 compiler is not finished yet. This is only used for debuggging!"); try { diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/UnresolvedAVM2Item.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/UnresolvedAVM2Item.java index 0993722a9..5a5fd8bae 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/UnresolvedAVM2Item.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/UnresolvedAVM2Item.java @@ -457,7 +457,7 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item { if (paramNames.contains(parts.get(0)) || parts.get(0).equals("arguments")) { int ind = paramNames.indexOf(parts.get(0)); - GraphTargetItem ret = new NameAVM2Item(ind == -1 ? TypeItem.UNBOUNDED : paramTypes.get(ind), line, name, null, false, openedNamespaces); + GraphTargetItem ret = new NameAVM2Item(ind == -1 ? TypeItem.UNBOUNDED : paramTypes.get(ind), line, parts.get(0), null, false, openedNamespaces); resolved = ret; for (int i = 1; i < parts.size(); i++) { resolved = new PropertyAVM2Item(resolved, parts.get(i), null, abc, otherAbcs, openedNamespaces, new ArrayList()); diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java b/trunk/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java index 1c9d1c55e..cfa194319 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java @@ -67,6 +67,14 @@ public class MethodBody implements Cloneable, Serializable { } return ret; } + + public void markOffsets(){ + long offset = 0; + for(int i=0;i