0001: /* -*- mode: java; c-basic-offset: 2; -*- */
0002:
0003: /***
0004: * Instructions.java
0005: *
0006: * Description: SWF Action Code instruction opcode constants
0007: */package org.openlaszlo.sc;
0008:
0009: import java.io.*;
0010: import java.nio.*;
0011: import java.util.*;
0012: import org.openlaszlo.sc.Actions.Action;
0013: import org.openlaszlo.sc.Values.*;
0014:
0015: public class Instructions {
0016: private static String runtime;
0017:
0018: public static void setRuntime(String target) {
0019: runtime = target.intern();
0020: }
0021:
0022: public static String getRuntime() {
0023: return runtime;
0024: }
0025:
0026: // Reverse lookup, for disassembly and compiling assembler
0027: public static Map ActionNames = new HashMap();
0028: static {
0029: for (Iterator i = Actions.actions.values().iterator(); i
0030: .hasNext();) {
0031: Action value = (Action) i.next();
0032: String name = value.name;
0033: // convert to flasm casification
0034: if (name.equals(name.toUpperCase())) {
0035: name = name.toLowerCase();
0036: } else {
0037: name = name.substring(0, 1).toLowerCase()
0038: + name.substring(1);
0039: }
0040: ActionNames.put(value, name);
0041: }
0042: }
0043:
0044: // Action -> String
0045: public static String actionName(Action op) {
0046: return (String) ActionNames.get(op);
0047: }
0048:
0049: /*
0050: * Instructions
0051: *
0052: * The code generator creates instructions, which are passed to the
0053: * assembler for pretty-printing or bytecode generation. Each
0054: * instruction knows how to print itself, and how to add its bytes to a
0055: * byte array.
0056: */
0057: public static Map NameInstruction = new HashMap();
0058:
0059: /***
0060: * Registers
0061: */
0062: public static class Register implements Serializable {
0063: public String name;
0064: public byte regno;
0065:
0066: public static Set AUTO_REG = new LinkedHashSet();
0067: static {
0068: AUTO_REG.add("this");
0069: AUTO_REG.add("arguments");
0070: AUTO_REG.add("super");
0071: AUTO_REG.add("_root");
0072: AUTO_REG.add("_parent");
0073: AUTO_REG.add("_global");
0074: }
0075:
0076: protected Register(String name) {
0077: this .name = name;
0078: this .regno = (byte) -1;
0079: }
0080:
0081: // Convenience
0082: static public Register make(int name) {
0083: return make(Integer.toString(name));
0084: }
0085:
0086: static public Register make(String name) {
0087: if (AUTO_REG.contains(name)) {
0088: return new AutoRegister(name);
0089: } else {
0090: return new Register(name);
0091: }
0092: }
0093:
0094: public String toString() {
0095: return "r:" + regno + "='" + name + "'";
0096: }
0097: }
0098:
0099: // Hard-wired registers that are automatically filled in,
0100: // according to the regflags
0101: public static class AutoRegister extends Register {
0102: public short flag;
0103: public short notFlag;
0104:
0105: public static Map FLAGS = new HashMap();
0106: static {
0107: FLAGS.put("this", new Integer(0x1));
0108: FLAGS.put("arguments", new Integer(0x4));
0109: FLAGS.put("super", new Integer(0x10));
0110: FLAGS.put("_root", new Integer(0x40));
0111: FLAGS.put("_parent", new Integer(0x80));
0112: FLAGS.put("_global", new Integer(0x100));
0113: }
0114:
0115: public static Map NOT_FLAGS = new HashMap();
0116: static {
0117: NOT_FLAGS.put("this", new Integer(0x2));
0118: NOT_FLAGS.put("arguments", new Integer(0x8));
0119: NOT_FLAGS.put("super", new Integer(0x20));
0120: NOT_FLAGS.put("_root", new Integer(0x0));
0121: NOT_FLAGS.put("_parent", new Integer(0x0));
0122: NOT_FLAGS.put("_global", new Integer(0x0));
0123: }
0124:
0125: // TODO: [2004-03-29 ptw] These flags turn off the creation of
0126: // this, arguments, and super in the activation record if they are
0127: // not used in the function body. Need to compute that from the
0128: // free references in the unlikely case that one of these is not
0129: // registered but still used (e.g., closed over).
0130: public static short DEFAULT_FLAGS = (short) (0x2 | 0x8 | 0x20);
0131:
0132: protected AutoRegister(String name) {
0133: super (name);
0134: flag = ((Integer) FLAGS.get(name)).shortValue();
0135: notFlag = ((Integer) NOT_FLAGS.get(name)).shortValue();
0136: }
0137: }
0138:
0139: /***
0140: * The abstract superclass of instructions. Subclasses are
0141: * ConcreteInstruction and PseudoInstruction.
0142: */
0143: public abstract static class Instruction implements Serializable {
0144: protected static final boolean[] curriedInstructions = new boolean[256];
0145:
0146: // default is to return null, meaning no information
0147: public StackModel updateStackModel(StackModel model) {
0148: return null;
0149: }
0150:
0151: public static Instruction curry(Action op) {
0152: Instruction inst;
0153: if (op == Actions.PUSH) {
0154: inst = new PUSHInstruction(op);
0155: } else if (op == Actions.DefineFunction) {
0156: inst = new DefineFunctionInstruction(op);
0157: } else if (op == Actions.DefineFunction2) {
0158: inst = new DefineFunction2Instruction(op);
0159: } else if (op == Actions.WITH) {
0160: inst = new WITHInstruction(op);
0161: } else if (op == Actions.TRY) {
0162: inst = new TryInstruction(op);
0163: } else if (BranchInstruction.OPCODES.contains(op)) {
0164: inst = new BranchInstruction(op);
0165: } else {
0166: inst = new ConcreteInstruction(op);
0167: }
0168: NameInstruction.put(actionName(op), inst);
0169: curriedInstructions[Actions.opcodeIndex(op.opcode)] = true;
0170: return inst;
0171: }
0172:
0173: public boolean isUnconditionalRedirect() {
0174: return false;
0175: }
0176:
0177: public abstract void writeBytes(ByteBuffer bytes, Map constants);
0178:
0179: // Python interface(s)
0180: public boolean getHasTarget() {
0181: return this instanceof TargetInstruction;
0182: }
0183:
0184: public boolean getIsLabel() {
0185: return this instanceof LABELInstruction;
0186: }
0187:
0188: public boolean getIsPush() {
0189: return this instanceof PUSHInstruction;
0190: }
0191:
0192: public boolean getIsBranchIfFalse() {
0193: return this instanceof BranchIfFalseInstruction;
0194: }
0195:
0196: public abstract Instruction make();
0197:
0198: // Convenience
0199: public Instruction make(int arg) {
0200: return make(new Integer(arg));
0201: }
0202:
0203: public abstract Instruction make(Object arg);
0204:
0205: public abstract Instruction make(Object[] args);
0206: }
0207:
0208: /***
0209: * Represents an instruction backed by bytecode.
0210: */
0211: public static class ConcreteInstruction extends Instruction {
0212: public Action op;
0213: public List args;
0214:
0215: protected ConcreteInstruction(Action op) {
0216: this (op, null);
0217: }
0218:
0219: protected ConcreteInstruction(Action op, List args) {
0220: super ();
0221: this .op = op;
0222: // Copy the arglist so it can be munged (e.g., push merging)
0223: if (args != null)
0224: this .args = new ArrayList(args);
0225: }
0226:
0227: public boolean isUnconditionalRedirect() {
0228: return op == Actions.RETURN || op == Actions.BRANCH;
0229: }
0230:
0231: public Object readResolve() {
0232: if (curriedInstructions[Actions.opcodeIndex(op.opcode)]
0233: && this .args == null)
0234: return (Instruction) NameInstruction
0235: .get(actionName(op));
0236: return this ;
0237: }
0238:
0239: public Instruction make() {
0240: assert (!this .op.args);
0241: return this ;
0242: }
0243:
0244: public Instruction make(Object arg) {
0245: assert this .op.args;
0246: return new ConcreteInstruction(this .op, Collections
0247: .singletonList(arg));
0248: }
0249:
0250: public Instruction make(Object[] args) {
0251: assert this .op.args;
0252: return new ConcreteInstruction(this .op, Arrays.asList(args));
0253: }
0254:
0255: public String toString() {
0256: Action op = this .op;
0257: String s = actionName(op);
0258: if (this .args != null) {
0259: s += " " + this .argsString();
0260: }
0261: return s;
0262: }
0263:
0264: public StackModel updateStackModel(StackModel model) {
0265: Action op = this .op;
0266: int arity = op.arity;
0267: int returns = op.returns;
0268: // Compute the arity for vararg instructions from the stack model
0269: // TODO: [2002-11-24 ptw] separate classes rather than re-dispatching
0270: if (op == Actions.CallFunction || op == Actions.NEW) {
0271: if (model.size() >= 2
0272: && Values.isInteger(model.get(-2))) {
0273: arity = ((Number) model.get(-2)).intValue() + 2;
0274: returns = 1;
0275: } else {
0276: arity = -1;
0277: returns = -1;
0278: }
0279: } else if (op == Actions.CallMethod
0280: || op == Actions.NewMethod) {
0281: if (model.size() >= 3
0282: && Values.isInteger(model.get(-3))) {
0283: arity = ((Number) model.get(-3)).intValue() + 3;
0284: returns = 1;
0285: } else {
0286: arity = -1;
0287: returns = -1;
0288: }
0289: } else if (op == Actions.InitArray) {
0290: if (model.size() >= 1
0291: && Values.isInteger(model.get(-1))) {
0292: arity = ((Number) model.get(-1)).intValue() + 1;
0293: returns = 1;
0294: } else {
0295: arity = -1;
0296: returns = -1;
0297: }
0298: } else if (op == Actions.InitObject) {
0299: if (model.size() >= 1
0300: && Values.isInteger(model.get(-1))) {
0301: arity = ((Number) model.get(-1)).intValue() * 2 + 1;
0302: returns = 1;
0303: } else {
0304: arity = -1;
0305: returns = -1;
0306: }
0307: }
0308: // System.out.println(this.toString() + " arity: " + arity + " returns: " + returns);
0309: // Adjust the stack model according to the instruction arity
0310: if (arity != -1 && returns != -1) {
0311: // TODO [2002-12-24 ptw] For now, we just invalidate any
0312: // information in the model. We could interpret some
0313: // instructions to update the model, but it is only used
0314: // for calls right now
0315: if (model.size() >= arity) {
0316: model.removeRange((-arity), model.size());
0317: model.addAll(Collections.nCopies(returns, null));
0318: return model;
0319: } else {
0320: // Needed operands outside of this block
0321: return null;
0322: }
0323: } else {
0324: return null;
0325: }
0326: }
0327:
0328: public String argsString() {
0329: Action op = this .op;
0330: if (op == Actions.SetRegister) {
0331: return "r:" + this .args.get(0).toString();
0332: } else {
0333: StringBuffer s = new StringBuffer();
0334: for (Iterator i = this .args.iterator(); i.hasNext();) {
0335: Object next = i.next();
0336: s.append("'" + next.toString() + "'");
0337: if (i.hasNext())
0338: s.append(" ");
0339: }
0340: return s.toString();
0341: }
0342: }
0343:
0344: /***
0345: * Appends the bytecode to bytes, resolving constant references
0346: * against constants.
0347: */
0348: public void writeBytes(ByteBuffer bytes, Map constants) {
0349: assert bytes.order() == ByteOrder.LITTLE_ENDIAN;
0350: bytes.put(this .op.opcode);
0351: // Flash has two types of instructions: single-byte instructions,
0352: // which have their low bit set, and multi-byte instructions, in which
0353: // the opcode byte is followed by a two-byte length word.
0354: if ((this .op.opcode & 0x80) != 0) {
0355: int offset = bytes.position();
0356: bytes.putShort((short) 0);
0357: if (this .op.args) {
0358: this .writeArgs(bytes, constants);
0359: int size = bytes.position() - offset - 2;
0360: if (size > ((1 << 16) - 1)) {
0361: throw new CompilerException(
0362: /* (non-Javadoc)
0363: * @i18n.test
0364: * @org-mes="offset out of range in " + p[0]
0365: */
0366: org.openlaszlo.i18n.LaszloMessages.getMessage(
0367: Instructions.class.getName(),
0368: "051018-366", new Object[] { this }));
0369: }
0370: bytes.putShort(offset, (short) size);
0371: }
0372: }
0373: }
0374:
0375: public void writeArgs(ByteBuffer bytes, Map constants) {
0376: Action op = this .op;
0377: List args = this .args;
0378: if (op == Actions.CONSTANTS) {
0379: int n = args.size();
0380: if (n > ((1 << 16) - 1)) {
0381: throw new CompilerException(
0382: /* (non-Javadoc)
0383: * @i18n.test
0384: * @org-mes="too many arguments in " + p[0]
0385: */
0386: org.openlaszlo.i18n.LaszloMessages.getMessage(
0387: Instructions.class.getName(), "051018-386",
0388: new Object[] { this }));
0389: }
0390: bytes.putShort((short) n);
0391: try {
0392: for (Iterator i = args.iterator(); i.hasNext();) {
0393: String encoding = "UTF-8";
0394: bytes.put(((String) i.next())
0395: .getBytes(encoding));
0396: bytes.put((byte) 0);
0397: }
0398: } catch (UnsupportedEncodingException e) {
0399: assert false : "this can't happen";
0400: }
0401: } else if (op == Actions.SetRegister) {
0402: Integer regno = ((Integer) args.get(0));
0403: if (regno.intValue() != regno.byteValue()) {
0404: throw new CompilerException(
0405: /* (non-Javadoc)
0406: * @i18n.test
0407: * @org-mes="invalid register number"
0408: */
0409: org.openlaszlo.i18n.LaszloMessages.getMessage(
0410: Instructions.class.getName(), "051018-408"));
0411: }
0412: bytes.put(regno.byteValue());
0413: } else if (op == Actions.GetURL2) {
0414: Integer flags = ((Integer) args.get(0));
0415: if (flags.intValue() != flags.byteValue()) {
0416: throw new CompilerException(
0417: "Invalid FLAGS for GetURL2");
0418: }
0419: bytes.put(flags.byteValue());
0420: // TODO: [2007-02-08 ptw] Are there more args? The variables
0421: // to send?
0422: } else {
0423: throw new CompilerException(
0424: /* (non-Javadoc)
0425: * @i18n.test
0426: * @org-mes="unimplemented: code generation for " + p[0]
0427: */
0428: org.openlaszlo.i18n.LaszloMessages.getMessage(
0429: Instructions.class.getName(), "051018-419",
0430: new Object[] { this .toString() }));
0431: }
0432: }
0433:
0434: // This is an upper bound estimate for most instructions
0435: public int argsBytes() {
0436: Action op = this .op;
0437: if (op == Actions.CONSTANTS) {
0438: int b = 2;
0439: try {
0440: String encoding = "UTF-8";
0441: for (Iterator i = this .args.iterator(); i.hasNext();) {
0442: b += ((String) i.next()).getBytes(encoding).length + 1;
0443: }
0444: } catch (UnsupportedEncodingException e) {
0445: assert false : "this can't happen";
0446: }
0447: return b;
0448: } else if (op == Actions.SetRegister
0449: || op == Actions.GetURL2) {
0450: return 1;
0451: } else {
0452: return 0;
0453: }
0454: }
0455: }
0456:
0457: /***
0458: * Target instructions have a target. During code generation, this is
0459: * a label (an arbitrary object, currently a string). During assembly,
0460: * this is replaced by an integer offset.
0461: */
0462: public abstract static class TargetInstruction extends
0463: ConcreteInstruction {
0464: public short targetOffset;
0465:
0466: protected TargetInstruction(Action op) {
0467: this (op, null);
0468: }
0469:
0470: protected TargetInstruction(Action op, List args) {
0471: this (op, args, (short) 0);
0472: }
0473:
0474: protected TargetInstruction(Action op, List args,
0475: short targetOffset) {
0476: super (op, args);
0477: this .targetOffset = targetOffset;
0478: }
0479:
0480: public Instruction make(Object arg) {
0481: return makeTargetInstruction(Collections.singletonList(arg));
0482: }
0483:
0484: public Instruction make(Object[] args) {
0485: return makeTargetInstruction(Arrays.asList(args));
0486: }
0487:
0488: public abstract TargetInstruction makeTargetInstruction(
0489: List args);
0490:
0491: public Object getTarget() {
0492: return this .args.get(0);
0493: }
0494:
0495: public TargetInstruction replaceTarget(Object target) {
0496: TargetInstruction replace = makeTargetInstruction(this .args);
0497: replace.args.set(0, target);
0498: return replace;
0499: }
0500:
0501: public void writeArgs(ByteBuffer bytes, Map pool) {
0502: assert bytes.order() == ByteOrder.LITTLE_ENDIAN;
0503: bytes.putShort(this .targetOffset);
0504: }
0505:
0506: public int argsBytes() {
0507: return 2;
0508: }
0509:
0510: // The offset of the target part of the instruction.
0511: // If positive, it is relative from the beginning of the instruction,
0512: // If negative, it is relative from the end.
0513: // Default version has branch target as last two bytes
0514:
0515: public int targetOffset(int whichTarget) {
0516: return -2;
0517: }
0518:
0519: }
0520:
0521: public static class WITHInstruction extends TargetInstruction {
0522:
0523: protected WITHInstruction(Action op) {
0524: this (op, null);
0525: }
0526:
0527: protected WITHInstruction(Action op, List args) {
0528: this (op, args, (short) 0);
0529: }
0530:
0531: protected WITHInstruction(Action op, List args,
0532: short targetOffset) {
0533: super (op, args);
0534: assert op == Actions.WITH;
0535: this .targetOffset = targetOffset;
0536: }
0537:
0538: public TargetInstruction makeTargetInstruction(List args) {
0539: return new WITHInstruction(this .op, args);
0540: }
0541: }
0542:
0543: public static class BranchInstruction extends TargetInstruction {
0544:
0545: // These are all the actions that have this type.
0546: public static Set OPCODES = new HashSet();
0547: static {
0548: OPCODES.add(Actions.BRANCH);
0549: OPCODES.add(Actions.BranchIfTrue);
0550: }
0551:
0552: protected BranchInstruction(Action op) {
0553: this (op, null);
0554: }
0555:
0556: protected BranchInstruction(Action op, List args) {
0557: this (op, args, (short) 0);
0558: }
0559:
0560: protected BranchInstruction(Action op, List args,
0561: short targetOffset) {
0562: super (op, args);
0563: assert OPCODES.contains(op);
0564: this .targetOffset = targetOffset;
0565: }
0566:
0567: public TargetInstruction makeTargetInstruction(List args) {
0568: return new BranchInstruction(this .op, args);
0569: }
0570: }
0571:
0572: public static class TryInstruction extends TargetInstruction {
0573:
0574: // inherited targetOffset is ignored
0575:
0576: short blockStart;
0577: short catchStart;
0578: short finallyStart;
0579: short blockEnd;
0580: public static int FLAGS_HAS_CATCH = 0x1;
0581: public static int FLAGS_HAS_FINALLY = 0x2;
0582:
0583: protected TryInstruction(Action op) {
0584: this (op, null);
0585: }
0586:
0587: protected TryInstruction(Action op, List args) {
0588: this (op, args, (short) 0, (short) 0, (short) 0, (short) 0);
0589: }
0590:
0591: protected TryInstruction(Action op, List args,
0592: short blockStart, short catchStart, short finallyStart,
0593: short blockEnd) {
0594: super (op, args);
0595: assert op == Actions.TRY;
0596: this .blockStart = blockStart;
0597: this .catchStart = catchStart;
0598: this .finallyStart = finallyStart;
0599: this .blockEnd = blockEnd;
0600: }
0601:
0602: // The args are 6 labels, a variable name for the exception, and flags.
0603: // The labels are three pairs - each pair represents label arithmetic,
0604: // e.g. label1 - label0 to represent the size of a code block.
0605:
0606: public TargetInstruction makeTargetInstruction(List args) {
0607: return new TryInstruction(this .op, args);
0608: }
0609:
0610: // multiple target by returning an array
0611: public Object getTarget() {
0612: Object[] result = new Object[6];
0613: for (int i = 0; i < 6; i++)
0614: result[i] = this .args.get(i);
0615: return result;
0616: }
0617:
0618: public TargetInstruction replaceTarget(Object target) {
0619: TargetInstruction replace = makeTargetInstruction(this .args);
0620: Object[] targetarr = (Object[]) target;
0621: for (int i = 0; i < 6; i++)
0622: replace.args.set(i, targetarr[i]);
0623: return replace;
0624: }
0625:
0626: public void writeArgs(ByteBuffer bytes, Map pool) {
0627: assert bytes.order() == ByteOrder.LITTLE_ENDIAN;
0628: List args = this .args;
0629: byte flags = (byte) ((Integer) args.get(7)).intValue();
0630: bytes.put(flags);
0631: bytes.putShort(this .catchStart);
0632: bytes.putShort(this .finallyStart);
0633: bytes.putShort(this .blockEnd);
0634: String varname = (String) args.get(6);
0635: if (varname == null)
0636: varname = "";
0637: try {
0638: bytes.put(varname.getBytes("UTF-8"));
0639: } catch (UnsupportedEncodingException e) {
0640: assert false : "this can't happen";
0641: }
0642: bytes.put((byte) 0);
0643: }
0644:
0645: public int argsBytes() {
0646: List args = this .args;
0647: String varname = (String) args.get(3);
0648: if (varname == null)
0649: varname = "";
0650: // size => 1 byte flag + three targets + string + null
0651: int b = 1 + 6 + varname.length() + 1;
0652: return b;
0653: }
0654:
0655: public int targetOffset(int whichTarget) {
0656:
0657: // There are three targets to be filled,
0658: // each is a two byte value, and they begin
0659: // at byte 4 (after the flags)
0660:
0661: return 4 + whichTarget * 2;
0662: }
0663:
0664: public String toString() {
0665: StringBuffer b = new StringBuffer();
0666: b.append("try '" + (String) this .args.get(3) + "'");
0667: return b.toString();
0668: }
0669:
0670: }
0671:
0672: public static class DefineFunctionInstruction extends
0673: TargetInstruction {
0674:
0675: protected DefineFunctionInstruction(Action op) {
0676: this (op, null);
0677: }
0678:
0679: protected DefineFunctionInstruction(Action op, List args) {
0680: this (op, args, (short) 0);
0681: }
0682:
0683: protected DefineFunctionInstruction(Action op, List args,
0684: short targetOffset) {
0685: super (op, args);
0686: assert op == Actions.DefineFunction
0687: || op == Actions.DefineFunction2 : "Invalid op "
0688: + op.toString();
0689: this .targetOffset = targetOffset;
0690: }
0691:
0692: public TargetInstruction makeTargetInstruction(List args) {
0693: return new DefineFunctionInstruction(
0694: Actions.DefineFunction, args);
0695: }
0696:
0697: public void writeArgs(ByteBuffer bytes, Map pool) {
0698: assert bytes.order() == ByteOrder.LITTLE_ENDIAN;
0699: try {
0700: List args = this .args;
0701: String fname = (String) args.get(1);
0702: if (fname == null)
0703: fname = "";
0704: List fnargs = args.subList(2, args.size());
0705: int nargs = fnargs.size();
0706: bytes.put(fname.getBytes("UTF-8"));
0707: bytes.put((byte) 0);
0708: if (nargs != (short) nargs) {
0709: throw new CompilerException(
0710: /* (non-Javadoc)
0711: * @i18n.test
0712: * @org-mes="too many arguments"
0713: */
0714: org.openlaszlo.i18n.LaszloMessages.getMessage(
0715: Instructions.class.getName(), "051018-585"));
0716: }
0717: bytes.putShort((short) nargs);
0718: for (Iterator i = fnargs.iterator(); i.hasNext();) {
0719: bytes.put(((String) i.next()).getBytes("UTF-8"));
0720: bytes.put((byte) 0);
0721: }
0722: bytes.putShort(this .targetOffset);
0723: } catch (UnsupportedEncodingException e) {
0724: assert false : "this can't happen";
0725: }
0726: }
0727:
0728: public int argsBytes() {
0729: List args = this .args;
0730: String fname = (String) args.get(1);
0731: if (fname == null)
0732: fname = "";
0733: args = args.subList(2, args.size());
0734: int b = fname.length() + 1 + 2; // Geez, why not just size!?!?
0735: for (Iterator i = args.iterator(); i.hasNext();) {
0736: b += ((String) i.next()).length() + 1;
0737: }
0738: b += 2;
0739: return b;
0740: }
0741:
0742: public String toString() {
0743: StringBuffer b = new StringBuffer();
0744: b.append("function ");
0745: Object name = this .args.get(1);
0746: if (name != null) {
0747: b.append(name.toString());
0748: }
0749: b.append("(");
0750: List args = this .args.subList(2, this .args.size());
0751: for (Iterator i = args.iterator(); i.hasNext();) {
0752: Object next = i.next();
0753: // --- better way to escape strings?
0754: if (next instanceof String) {
0755: b.append("'" + next.toString() + "'");
0756: } else {
0757: b.append(next.toString());
0758: }
0759: if (i.hasNext())
0760: b.append(", ");
0761: }
0762: b.append(")");
0763: return b.toString();
0764: }
0765: }
0766:
0767: /*
0768: * Flash 7 DefineFunction2 Instruction
0769: *
0770: * Similar to function, but parameters can be assigned to
0771: * 'registers'
0772: * Output format: string name, short nargs, byte nregs, short
0773: * regflags, [byte regno, string arg]*, short ninstrs
0774: */
0775: public static class DefineFunction2Instruction extends
0776: DefineFunctionInstruction {
0777:
0778: protected DefineFunction2Instruction(Action op) {
0779: this (op, null);
0780: }
0781:
0782: protected DefineFunction2Instruction(Action op, List args) {
0783: this (op, args, (short) 0);
0784: }
0785:
0786: protected DefineFunction2Instruction(Action op, List args,
0787: short targetOffset) {
0788: super (op, args);
0789: assert op == Actions.DefineFunction2;
0790: this .targetOffset = targetOffset;
0791: }
0792:
0793: public TargetInstruction makeTargetInstruction(List args) {
0794: return new DefineFunction2Instruction(
0795: Actions.DefineFunction2, args);
0796: }
0797:
0798: public void writeArgs(ByteBuffer bytes, Map pool) {
0799: assert bytes.order() == ByteOrder.LITTLE_ENDIAN;
0800: try {
0801: List args = this .args;
0802: String fname = (String) args.get(1);
0803: if (fname == null)
0804: fname = "";
0805: byte nregs = ((Integer) args.get(2)).byteValue();
0806: List fnargs = args.subList(3, args.size());
0807: // string name
0808: bytes.put(fname.getBytes("UTF-8"));
0809: bytes.put((byte) 0);
0810: // short nargs (will be back-patched)
0811: short nargs = 0;
0812: int nargsPos = bytes.position();
0813: bytes.putShort(nargs);
0814: // byte nregs
0815: bytes.put(nregs);
0816: // short regflags (will be back-patched)
0817: short regflags = AutoRegister.DEFAULT_FLAGS;
0818: int regflagsPos = bytes.position();
0819: bytes.putShort((short) 0);
0820: for (Iterator i = fnargs.iterator(); i.hasNext();) {
0821: Object arg = i.next();
0822: if (arg instanceof Register) {
0823: Register reg = (Register) arg;
0824: nregs++;
0825: if (reg instanceof AutoRegister) {
0826: AutoRegister areg = (AutoRegister) reg;
0827: regflags &= ~(areg.notFlag);
0828: regflags |= areg.flag;
0829: } else {
0830: nargs++;
0831: // byte regno
0832: bytes.put(reg.regno);
0833: // string arg
0834: bytes.put(reg.name.getBytes("UTF-8"));
0835: bytes.put((byte) 0);
0836: }
0837: } else if (arg instanceof String) {
0838: nargs++;
0839: // byte regno
0840: // 0 means not registered
0841: bytes.put((byte) 0);
0842: // string arg
0843: bytes.put(((String) arg).getBytes("UTF-8"));
0844: bytes.put((byte) 0);
0845: } else {
0846: System.out.println("Unknown arg: " + arg);
0847: }
0848: }
0849: // Backpatch nregs and flags
0850: bytes.putShort(nargsPos, nargs);
0851: bytes.putShort(regflagsPos, regflags);
0852: // short ninstrs
0853: bytes.putShort(this .targetOffset);
0854: } catch (UnsupportedEncodingException e) {
0855: assert false : "this can't happen";
0856: }
0857: }
0858:
0859: public int argsBytes() {
0860: List args = this .args;
0861: String fname = (String) args.get(1);
0862: if (fname == null)
0863: fname = "";
0864: args = args.subList(2, args.size());
0865: int b = fname.length() + 1 + 2 + 1 + 2; // Geez, why not just size!?!?
0866: for (Iterator i = args.iterator(); i.hasNext();) {
0867: Object arg = i.next();
0868: if (arg instanceof Register) {
0869: if (arg instanceof AutoRegister) {
0870: ;
0871: } else {
0872: b += 1 + ((Register) arg).name.length() + 1;
0873: }
0874: } else {
0875: b += ((String) arg).length() + 1;
0876: }
0877: }
0878: b += 2;
0879: return b;
0880: }
0881:
0882: public String toString() {
0883: StringBuffer b = new StringBuffer();
0884: b.append("function2 ");
0885: Object name = this .args.get(1);
0886: if (name != null) {
0887: b.append(name.toString());
0888: }
0889: List args = this .args.subList(3, this .args.size());
0890: b.append("(");
0891: for (Iterator i = args.iterator(); i.hasNext();) {
0892: Object next = i.next();
0893: if (next instanceof AutoRegister) {
0894: continue;
0895: }
0896: if (next instanceof String) {
0897: // --- better way to escape strings?
0898: b.append("'" + next.toString() + "'");
0899: } else {
0900: b.append(next.toString());
0901: }
0902: if (i.hasNext())
0903: b.append(", ");
0904: }
0905: b.append(") (");
0906: for (Iterator i = args.iterator(); i.hasNext();) {
0907: Object next = i.next();
0908: boolean firsttime = true;
0909: if (next instanceof AutoRegister) {
0910: if (firsttime) {
0911: firsttime = false;
0912: } else {
0913: b.append(", ");
0914: }
0915: b.append(next.toString());
0916: }
0917: }
0918: b.append(")");
0919: return b.toString();
0920: }
0921: }
0922:
0923: public static class PUSHInstruction extends ConcreteInstruction {
0924: private int cachedArgsBytes;
0925:
0926: protected PUSHInstruction(Action op) {
0927: this (op, null);
0928: }
0929:
0930: protected PUSHInstruction(Action op, List args) {
0931: super (Actions.PUSH, args);
0932: assert op == Actions.PUSH;
0933: this .cachedArgsBytes = -1;
0934: }
0935:
0936: public PUSHInstruction(List args) {
0937: this (Actions.PUSH, args);
0938: }
0939:
0940: // Python interfaces
0941: public Instruction make(Object arg) {
0942: assert arg instanceof Number || arg instanceof Value
0943: || arg instanceof String || arg instanceof Boolean;
0944: return new PUSHInstruction(Collections.singletonList(arg));
0945: }
0946:
0947: public Instruction make(Object[] args) {
0948: for (Iterator i = this .args.iterator(); i.hasNext();) {
0949: Object arg = i.next();
0950: assert arg instanceof Number || arg instanceof Value
0951: || arg instanceof String
0952: || arg instanceof Boolean;
0953: }
0954: return new PUSHInstruction(Arrays.asList(args));
0955: }
0956:
0957: public boolean isVolatile() {
0958: for (Iterator i = this .args.iterator(); i.hasNext();) {
0959: if (Values.isRegister(i.next())) {
0960: return true;
0961: }
0962: }
0963: return false;
0964: }
0965:
0966: public int argsBytes() {
0967: if (this .cachedArgsBytes == -1) {
0968: this .cachedArgsBytes = this .computeArgsBytes(this .args);
0969: }
0970: return this .cachedArgsBytes;
0971: }
0972:
0973: public StackModel updateStackModel(StackModel model) {
0974: model.notePush(this , this .argsModel());
0975: return model;
0976: }
0977:
0978: // Return the args in a format for the stack model. Only
0979: // numbers and strings are modelled (for vararg instructions)
0980: private List argsModel() {
0981: List model = new ArrayList();
0982: for (Iterator i = this .args.iterator(); i.hasNext();) {
0983: Object v = i.next();
0984: if (v instanceof String || v instanceof Number) {
0985: model.add(v);
0986: } else {
0987: model.add(null);
0988: }
0989: }
0990: return model;
0991: }
0992:
0993: public boolean merge(PUSHInstruction other, StackModel model) {
0994: // Limit of multi-byte instruction length
0995: if (this .argsBytes() + other.argsBytes() >= 65536) {
0996: return false;
0997: }
0998: // We know they are cached now
0999: this .cachedArgsBytes += other.cachedArgsBytes;
1000: // Merged args are inserted after the args that are still on
1001: // the stack
1002: int i = model.pushDepth(this );
1003: this .args.addAll(i, other.args);
1004: model.notePush(this , other.argsModel());
1005: return true;
1006: }
1007:
1008: // Can only make this optimization if the last value is still on
1009: // the stack
1010: public boolean dup(StackModel model) {
1011: int i = model.pushDepth(this );
1012: if (i > 0) {
1013: Object last = this .args.get(i - 1);
1014: if (model.size() >= 1 && model.get(-1) == last) {
1015: List lastargs = Collections.singletonList(last);
1016: int lastBytes = this .computeArgsBytes(lastargs);
1017: // Limit of multi-byte instruction length
1018: if (this .argsBytes() + lastBytes >= 65536) {
1019: return false;
1020: }
1021: // Must have been cached above
1022: this .cachedArgsBytes += lastBytes;
1023: this .args.addAll(i, lastargs);
1024: model.notePush(this , lastargs);
1025: return true;
1026: } else {
1027: // System.out.println("dup.i: " + i);
1028: // System.out.println("dup.model: " + model);
1029: return false;
1030: }
1031: } else {
1032: return false;
1033: }
1034: }
1035:
1036: public void writeArgs(ByteBuffer bytes, Map constants) {
1037: assert bytes.order() == ByteOrder.LITTLE_ENDIAN;
1038: try {
1039: for (Iterator i = this .args.iterator(); i.hasNext();) {
1040: Object o = i.next();
1041:
1042: // Numbers are written as integers or floats if there is no
1043: // loss of precision, otherwise as doubles
1044: // FIXME [2002-02-25 ptw] Use a language with dynamic dispatch
1045: if (o instanceof Number) {
1046: Number n = (Number) o;
1047: if (n.doubleValue() == n.intValue()) {
1048: bytes.put(PushTypes.Integer);
1049: bytes.putInt(n.intValue());
1050: } else if (n.doubleValue() == n.floatValue()) {
1051: bytes.put(PushTypes.Float);
1052: bytes.putFloat(n.floatValue());
1053: } else {
1054: bytes.put(PushTypes.Double);
1055: // SWF has the opposite word order
1056: long lb = Double.doubleToRawLongBits(n
1057: .doubleValue());
1058: bytes.putInt((int) (lb >> 32));
1059: bytes.putInt((int) lb);
1060: }
1061: } else if (o instanceof Value) {
1062: Value v = (Value) o;
1063: bytes.put(v.type);
1064: if (v instanceof ParameterizedValue) {
1065: bytes.put(((ParameterizedValue) v).value);
1066: }
1067: } else if (o instanceof Boolean) {
1068: Value v = ((Boolean) o).booleanValue() ? Values.True
1069: : Values.False;
1070: bytes.put(v.type);
1071: if (v instanceof ParameterizedValue) {
1072: bytes.put(((ParameterizedValue) v).value);
1073: }
1074: } else if (o instanceof String) {
1075: String s = (String) o;
1076: if (constants != null
1077: && constants.containsKey(s)) {
1078: int index = ((Integer) constants.get(s))
1079: .intValue();
1080: if (index < 1 << 8) {
1081: bytes.put(PushTypes.CONSTANT_INDEX8);
1082: bytes.put((byte) index);
1083: } else {
1084: assert index < 1 << 16;
1085: bytes.put(PushTypes.CONSTANT_INDEX16);
1086: bytes.putShort((short) index);
1087: }
1088: } else {
1089: bytes.put(PushTypes.String);
1090: bytes.put(s.getBytes("UTF-8"));
1091: bytes.put((byte) 0);
1092: }
1093: } else {
1094: throw new CompilerException(
1095: "Unknown type for PUSH: " + o
1096: + " (in args " + this .args
1097: + ")");
1098: }
1099: }
1100: } catch (UnsupportedEncodingException e) {
1101: assert false : "this can't happen, but Java is too stupid to know that";
1102: }
1103: }
1104:
1105: // compute an upper bound for the size of the arguments. cf., computePushArg
1106: public int computeArgsBytes(List args) {
1107: // 'exact' answer
1108: // int b = 0;
1109: // for (Iterator i = args.iterator(); i.hasNext(); ) {
1110: // b += computePushArg(i.next()).size;
1111: // }
1112: // return b;
1113: // quick upper bound instead:
1114: int b = 0;
1115: for (Iterator i = args.iterator(); i.hasNext();) {
1116: Object o = i.next();
1117:
1118: if (o instanceof Number) {
1119: Number n = (Number) o;
1120: if (n.doubleValue() == n.intValue()) {
1121: b += 1 + 4;
1122: } else if (n.doubleValue() == n.floatValue()) {
1123: b += 1 + 4;
1124: } else {
1125: b += 1 + 8;
1126: }
1127: } else if (o instanceof Value) {
1128: Value v = (Value) o;
1129: b += 1;
1130: if (v instanceof ParameterizedValue) {
1131: b += 1;
1132: }
1133: } else if (o instanceof String) {
1134: try {
1135: String s = (String) o;
1136: b += 1 + (s.getBytes("UTF-8").length) + 1;
1137: } catch (UnsupportedEncodingException e) {
1138: assert false : "this can't happen, but Java is too stupid to know that";
1139: }
1140: }
1141: }
1142: return b;
1143: }
1144:
1145: // Python interface to PUSHInstruction constants
1146: public List getargs() {
1147: return this .args;
1148: }
1149: }
1150:
1151: // Pseudo-instructions used during assembly
1152:
1153: /***
1154: * Represents an instruction that isn't backed by bytecode.
1155: * PseudoInstructions are resolved by the assembler.
1156: */
1157: public static class PseudoInstruction extends Instruction {
1158: public Object name;
1159:
1160: public PseudoInstruction(Object name) {
1161: this .name = name;
1162: }
1163:
1164: public String toString() {
1165: return this .name.toString();
1166: }
1167:
1168: public void writeBytes(ByteBuffer bytes, Map constants) {
1169: assert bytes.order() == ByteOrder.LITTLE_ENDIAN;
1170: ;
1171: }
1172:
1173: public int argsBytes() {
1174: return 0;
1175: }
1176:
1177: public Instruction make() {
1178: assert false;
1179: return null;
1180: }
1181:
1182: public Instruction make(Object arg) {
1183: assert false;
1184: return null;
1185: }
1186:
1187: public Instruction make(Object[] args) {
1188: assert false;
1189: return null;
1190: }
1191: }
1192:
1193: /***
1194: * A BranchIfFalse pseudo-instruction is used to simplify the code
1195: * generator. It is replaced by (NOT, BranchIfTrue) when the code
1196: * generator emits to the assembler
1197: */
1198: public static class BranchIfFalseInstruction extends
1199: PseudoInstruction {
1200:
1201: protected BranchIfFalseInstruction(Object target) {
1202: super (target);
1203: }
1204:
1205: public Instruction make(Object target) {
1206: return new BranchIfFalseInstruction(target);
1207: }
1208:
1209: public Instruction make(int target) {
1210: return new BranchIfFalseInstruction(new Integer(target));
1211: }
1212:
1213: public String toString() {
1214: return "branchIfFalse " + this .name;
1215: }
1216:
1217: // Python interface
1218: public Object getTarget() {
1219: return this .name;
1220: }
1221: }
1222:
1223: /***
1224: * A LABEL pseudo-instruction of the form @code{LABEL(n)} is added to
1225: * the instruction sequence at the target for a label. (Label targets
1226: * are used for conditional expressions, control structures, and the
1227: * ends of definitions and @code{with} statements.)
1228: */
1229: public static class LABELInstruction extends PseudoInstruction {
1230:
1231: protected LABELInstruction(Object name) {
1232: super (name);
1233: }
1234:
1235: public Instruction make(Object name) {
1236: return new LABELInstruction(name);
1237: }
1238:
1239: public Instruction make(int target) {
1240: return new LABELInstruction(new Integer(target));
1241: }
1242:
1243: public String toString() {
1244: return super .toString() + ":";
1245: }
1246: }
1247:
1248: public static class COMMENTInstruction extends PseudoInstruction {
1249:
1250: protected COMMENTInstruction(String comment) {
1251: super (comment);
1252: }
1253:
1254: public Instruction make(Object comment) {
1255: return new COMMENTInstruction((String) comment);
1256: }
1257:
1258: public String toString() {
1259: return ";; " + super .toString();
1260: }
1261:
1262: // Allow PUSHInstruction to optimize across this.
1263: public StackModel updateStackModel(StackModel model) {
1264: return model;
1265: }
1266: }
1267:
1268: // Print running statistics about the current assembly state
1269: public static class CHECKPOINTInstruction extends
1270: COMMENTInstruction {
1271: protected CHECKPOINTInstruction(String message) {
1272: super (message);
1273: }
1274:
1275: public Instruction make(Object message) {
1276: return new CHECKPOINTInstruction((String) message);
1277: }
1278:
1279: public void writeBytes(ByteBuffer bytes, Map constants) {
1280: assert bytes.order() == ByteOrder.LITTLE_ENDIAN;
1281: System.out.println(super .toString() + "\t"
1282: + bytes.position());
1283: }
1284: }
1285:
1286: // Pass arbitrary bytes into the object
1287: public static class BLOBInstruction extends PseudoInstruction {
1288: byte[] blob;
1289:
1290: protected BLOBInstruction(String repr, byte[] blob) {
1291: super (repr);
1292: this .blob = blob;
1293: }
1294:
1295: public Instruction make(String repr, byte[] blob) {
1296: return new BLOBInstruction(repr, blob);
1297: }
1298:
1299: public void writeBytes(ByteBuffer bytes, Map constants) {
1300: assert bytes.order() == ByteOrder.LITTLE_ENDIAN;
1301: bytes.put(this .blob);
1302: }
1303:
1304: public int argsBytes() {
1305: return (this .blob.length);
1306: }
1307: }
1308:
1309: // For each symbol in the actions package, create a symbol with the
1310: // same name in this package. If the instruction takes arguments,
1311: // the symbol names a constructor, otherwise it names an instance.
1312: // (This matches standard algebraic datatype syntax in functional
1313: // languages, and it ends up being more convenient and easier to use
1314: // than it sounds: for example, POP and BRANCH('label') are both
1315: // instructions.)
1316:
1317: public static Instruction NONE = Instruction.curry(Actions.NONE);
1318: public static Instruction NextFrame = Instruction
1319: .curry(Actions.NextFrame);
1320: public static Instruction PreviousFrame = Instruction
1321: .curry(Actions.PreviousFrame);
1322: public static Instruction PLAY = Instruction.curry(Actions.PLAY);
1323: public static Instruction STOP = Instruction.curry(Actions.STOP);
1324: public static Instruction ToggleQuality = Instruction
1325: .curry(Actions.ToggleQuality);
1326: public static Instruction StopSounds = Instruction
1327: .curry(Actions.StopSounds);
1328: public static Instruction NumericAdd = Instruction
1329: .curry(Actions.NumericAdd);
1330: public static Instruction SUBTRACT = Instruction
1331: .curry(Actions.SUBTRACT);
1332: public static Instruction MULTIPLY = Instruction
1333: .curry(Actions.MULTIPLY);
1334: public static Instruction DIVIDE = Instruction
1335: .curry(Actions.DIVIDE);
1336: public static Instruction OldEquals = Instruction
1337: .curry(Actions.OldEquals);
1338: public static Instruction OldLessThan = Instruction
1339: .curry(Actions.OldLessThan);
1340: public static Instruction LogicalAnd = Instruction
1341: .curry(Actions.LogicalAnd);
1342: public static Instruction LogicalOr = Instruction
1343: .curry(Actions.LogicalOr);
1344: public static Instruction NOT = Instruction.curry(Actions.NOT);
1345: public static Instruction StringEqual = Instruction
1346: .curry(Actions.StringEqual);
1347: public static Instruction StringLength = Instruction
1348: .curry(Actions.StringLength);
1349: public static Instruction SUBSTRING = Instruction
1350: .curry(Actions.SUBSTRING);
1351: public static Instruction POP = Instruction.curry(Actions.POP);
1352: public static Instruction INT = Instruction.curry(Actions.INT);
1353: public static Instruction GetVariable = Instruction
1354: .curry(Actions.GetVariable);
1355: public static Instruction SetVariable = Instruction
1356: .curry(Actions.SetVariable);
1357: public static Instruction SetTargetExpression = Instruction
1358: .curry(Actions.SetTargetExpression);
1359: public static Instruction StringConcat = Instruction
1360: .curry(Actions.StringConcat);
1361: public static Instruction GetProperty = Instruction
1362: .curry(Actions.GetProperty);
1363: public static Instruction SetProperty = Instruction
1364: .curry(Actions.SetProperty);
1365: public static Instruction DuplicateMovieClip = Instruction
1366: .curry(Actions.DuplicateMovieClip);
1367: public static Instruction RemoveClip = Instruction
1368: .curry(Actions.RemoveClip);
1369: public static Instruction TRACE = Instruction.curry(Actions.TRACE);
1370: public static Instruction StartDragMovie = Instruction
1371: .curry(Actions.StartDragMovie);
1372: public static Instruction StopDragMovie = Instruction
1373: .curry(Actions.StopDragMovie);
1374: public static Instruction StringLessThan = Instruction
1375: .curry(Actions.StringLessThan);
1376: public static Instruction RANDOM = Instruction
1377: .curry(Actions.RANDOM);
1378: public static Instruction MBLENGTH = Instruction
1379: .curry(Actions.MBLENGTH);
1380: public static Instruction ORD = Instruction.curry(Actions.ORD);
1381: public static Instruction CHR = Instruction.curry(Actions.CHR);
1382: public static Instruction GetTimer = Instruction
1383: .curry(Actions.GetTimer);
1384: public static Instruction MBSUBSTRING = Instruction
1385: .curry(Actions.MBSUBSTRING);
1386: public static Instruction MBORD = Instruction.curry(Actions.MBORD);
1387: public static Instruction MBCHR = Instruction.curry(Actions.MBCHR);
1388: public static Instruction GotoFrame = Instruction
1389: .curry(Actions.GotoFrame);
1390: public static Instruction GetUrl = Instruction
1391: .curry(Actions.GetUrl);
1392: public static Instruction WaitForFrame = Instruction
1393: .curry(Actions.WaitForFrame);
1394: public static Instruction SetTarget = Instruction
1395: .curry(Actions.SetTarget);
1396: public static Instruction GotoLabel = Instruction
1397: .curry(Actions.GotoLabel);
1398: public static Instruction WaitForFrameExpression = Instruction
1399: .curry(Actions.WaitForFrameExpression);
1400: public static Instruction PUSH = Instruction.curry(Actions.PUSH);
1401: public static Instruction BRANCH = Instruction
1402: .curry(Actions.BRANCH);
1403: public static Instruction GetURL2 = Instruction
1404: .curry(Actions.GetURL2);
1405: public static Instruction BranchIfTrue = Instruction
1406: .curry(Actions.BranchIfTrue);
1407: public static Instruction CallFrame = Instruction
1408: .curry(Actions.CallFrame);
1409: public static Instruction GotoExpression = Instruction
1410: .curry(Actions.GotoExpression);
1411:
1412: // Flash 5
1413: public static Instruction DELETE = Instruction
1414: .curry(Actions.DELETE);
1415: public static Instruction DELETE2 = Instruction
1416: .curry(Actions.DELETE2);
1417: public static Instruction VarEquals = Instruction
1418: .curry(Actions.VarEquals);
1419: public static Instruction CallFunction = Instruction
1420: .curry(Actions.CallFunction);
1421: public static Instruction RETURN = Instruction
1422: .curry(Actions.RETURN);
1423: public static Instruction MODULO = Instruction
1424: .curry(Actions.MODULO);
1425: public static Instruction NEW = Instruction.curry(Actions.NEW);
1426: public static Instruction VAR = Instruction.curry(Actions.VAR);
1427: public static Instruction InitArray = Instruction
1428: .curry(Actions.InitArray);
1429: public static Instruction InitObject = Instruction
1430: .curry(Actions.InitObject);
1431: public static Instruction TypeOf = Instruction
1432: .curry(Actions.TypeOf);
1433: public static Instruction TargetPath = Instruction
1434: .curry(Actions.TargetPath);
1435: public static Instruction ENUMERATE = Instruction
1436: .curry(Actions.ENUMERATE);
1437: public static Instruction ADD = Instruction.curry(Actions.ADD);
1438: public static Instruction LessThan = Instruction
1439: .curry(Actions.LessThan);
1440: public static Instruction EQUALS = Instruction
1441: .curry(Actions.EQUALS);
1442: public static Instruction ObjectToNumber = Instruction
1443: .curry(Actions.ObjectToNumber);
1444: public static Instruction ObjectToString = Instruction
1445: .curry(Actions.ObjectToString);
1446: public static Instruction DUP = Instruction.curry(Actions.DUP);
1447: public static Instruction SWAP = Instruction.curry(Actions.SWAP);
1448: public static Instruction GetMember = Instruction
1449: .curry(Actions.GetMember);
1450: public static Instruction SetMember = Instruction
1451: .curry(Actions.SetMember);
1452: public static Instruction Increment = Instruction
1453: .curry(Actions.Increment);
1454: public static Instruction Decrement = Instruction
1455: .curry(Actions.Decrement);
1456: public static Instruction CallMethod = Instruction
1457: .curry(Actions.CallMethod);
1458: public static Instruction NewMethod = Instruction
1459: .curry(Actions.NewMethod);
1460: public static Instruction BitwiseAnd = Instruction
1461: .curry(Actions.BitwiseAnd);
1462: public static Instruction BitwiseOr = Instruction
1463: .curry(Actions.BitwiseOr);
1464: public static Instruction BitwiseXor = Instruction
1465: .curry(Actions.BitwiseXor);
1466: public static Instruction ShiftLeft = Instruction
1467: .curry(Actions.ShiftLeft);
1468: public static Instruction ShiftRight = Instruction
1469: .curry(Actions.ShiftRight);
1470: public static Instruction UShiftRight = Instruction
1471: .curry(Actions.UShiftRight);
1472: public static Instruction SetRegister = Instruction
1473: .curry(Actions.SetRegister);
1474: public static Instruction CONSTANTS = Instruction
1475: .curry(Actions.CONSTANTS);
1476: public static Instruction WITH = Instruction.curry(Actions.WITH);
1477: public static Instruction DefineFunction = Instruction
1478: .curry(Actions.DefineFunction);
1479:
1480: // Flash 6
1481: public static Instruction InstanceOf = Instruction
1482: .curry(Actions.InstanceOf);
1483: public static Instruction EnumerateValue = Instruction
1484: .curry(Actions.EnumerateValue);
1485: public static Instruction StrictEquals = Instruction
1486: .curry(Actions.StrictEquals);
1487: public static Instruction GreaterThan = Instruction
1488: .curry(Actions.GreaterThan);
1489: public static Instruction StringGreaterThan = Instruction
1490: .curry(Actions.StringGreaterThan);
1491:
1492: // Flash 7
1493: public static Instruction DefineFunction2 = Instruction
1494: .curry(Actions.DefineFunction2);
1495: public static Instruction TRY = Instruction.curry(Actions.TRY);
1496: public static Instruction THROW = Instruction.curry(Actions.THROW);
1497:
1498: // Flash Lite 2
1499: public static Instruction FSCommand2 = Instruction
1500: .curry(Actions.FSCommand2);
1501:
1502: // Psuedo-instructions
1503: public static Instruction BranchIfFalse = new BranchIfFalseInstruction(
1504: "");
1505: public static Instruction LABEL = new LABELInstruction("");
1506: public static Instruction COMMENT = new COMMENTInstruction("");
1507: public static Instruction CHECKPOINT = new CHECKPOINTInstruction("");
1508: public static Instruction BLOB = new BLOBInstruction("", null);
1509: static {
1510: NameInstruction.put("BranchIfFalse", BranchIfFalse);
1511: NameInstruction.put("LABEL", LABEL);
1512: NameInstruction.put("COMMENT", COMMENT);
1513: NameInstruction.put("CHECKPOINT", CHECKPOINT);
1514: NameInstruction.put("BLOB", BLOB);
1515: }
1516: }
1517:
1518: /* J_LZ_COPYRIGHT_BEGIN *******************************************************
1519: * Copyright 2001-2007 Laszlo Systems, Inc. All Rights Reserved. *
1520: * Use is subject to license terms. *
1521: * J_LZ_COPYRIGHT_END *********************************************************/
|