/* * Copyright (c) 2007 BUSINESS OBJECTS SOFTWARE LIMITED * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of Business Objects nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Instruction.java * Creation date: (March 3 2000 5:21:47 PM) * By: Raymond Cypher */ package org.openquark.cal.internal.machine.g; import java.io.IOException; import java.math.BigInteger; import java.util.Map; import org.openquark.cal.compiler.DataConstructor; import org.openquark.cal.compiler.ForeignFunctionInfo; import org.openquark.cal.compiler.QualifiedName; import org.openquark.cal.internal.serialization.ModuleSerializationTags; import org.openquark.cal.internal.serialization.RecordOutputStream; import org.openquark.cal.machine.CALExecutor; import org.openquark.cal.module.Cal.Core.CAL_Prelude; import org.openquark.cal.runtime.CALExecutorException; import org.openquark.cal.runtime.ErrorInfo; import org.openquark.util.UnsafeCast; /** * A G-Machine instruction. * Creation date: (3/3/00 5:21:47 PM) * @author Raymond Cypher * * All G-Machine instructions are inheriting static nested classes of this class * The inherited classes should not contain any data members. If an inherited class * is created which contains a data member then the serialization mechanism will * need to be updated. * */ abstract class Instruction { static final int T_Alloc = 1; static final int T_Call = 2; static final int T_Cond = 3; static final int T_CondJ = 4; static final int T_Dispatch = 5; static final int T_ForeignFunctionCall = 6; static final int T_ClearStack = 7; static final int T_Eval = 8; static final int T_Instrument = 9; static final int T_PushFalse = 10; static final int T_PushTrue = 11; static final int T_Unwind = 12; static final int T_Jump = 13; static final int T_MkapN = 14; static final int T_PackCons = 15; static final int T_PackCons0 = 16; static final int T_PackCons2 = 17; static final int T_Pop = 18; static final int T_PrimOp = 19; static final int T_Push = 20; static final int T_PushGlobal = 21; static final int T_PushGlobalN = 22; static final int T_PushList = 23; static final int T_PushString = 24; static final int T_PushVVal = 25; static final int T_Slide = 26; static final int T_Split = 27; static final int T_Squeeze = 28; static final int T_Switch = 29; static final int T_SwitchJ = 30; static final int T_Update = 31; static final int T_CreateRecord = 32; static final int T_PutRecordField = 33; static final int T_ExtendRecord = 34; static final int T_RecordSelection = 35; static final int T_LazyRecordSelection = 36; static final int T_LazyRecordExtension = 37; static final int T_RemoveRecordField = 38; static final int T_Println = 39; static final int T_CreateList = 40; static final int T_PutListValue = 41; static final int T_Cast = 42; static final int T_PushPrimitiveNode = 43; static final int T_SelectDCField = 44; static final int T_LazySelectDCField = 45; static final int T_DebugProcessing = 46; static final int T_LazyRecordUpdate = 47; static final I_IClearStack I_ClearStack = new I_IClearStack (); static final I_IEval I_Eval = new I_IEval (); static final I_IUnwind I_Unwind = new I_IUnwind (); static final I_IPushTrue I_PushTrue = new I_IPushTrue (); static final I_IPushFalse I_PushFalse = new I_IPushFalse (); public static final int serializationSchema = 0; private final int tag; private final int n; // arity private final int m; // dc ordinal private final Object info; // dc runtime tag, PrimOp private final boolean bool; private final QualifiedName name; Instruction (int tag) { this.tag = tag; this.n = -1; this.m = -1; this.info = null; this.bool = true; this.name = null; } Instruction (int tag, int n) { this.tag = tag; this.n = n; this.m = -1; this.info = null; this.bool = true; this.name = null; } Instruction (int tag, int n, int m) { this.tag = tag; this.n = n; this.m = m; this.info = null; this.bool = true; this.name = null; } Instruction (int tag, Node node, boolean bool) { this.tag = tag; this.n = -1; this.m = -1; this.info = node; this.bool = bool; this.name = null; } Instruction (int tag, Object info) { this.tag = tag; this.n = -1; this.m = -1; this.info = info; this.bool = true; this.name = null; } Instruction (int tag, int n, Object info) { this.tag = tag; this.n = n; this.m = -1; this.info = info; this.bool = true; this.name = null; } Instruction (int tag, int n, int m, Object info, QualifiedName name) { this.tag = tag; this.n = n; this.m = m; this.info = info; this.bool = true; this.name = name; } int getTag () { return tag; } @Override public abstract String toString(); public abstract String toString(int indent); public void exec(CALExecutor e) throws CALExecutorException { } /** * @return n (arity) */ final int getN () { return n; } final Object getInfo () { return info; } final int getX () { return n; } final int getY () { return m; } /** * @return m (dc ordinal) */ final int getOrd () { return m; } /** * @return n (arity) */ final int getArity () { return n; } final QualifiedName getName () { if (name != null) { return name; } else { return (QualifiedName)info; } } Node getNode () { return (Node)info; } final Map<Object, Object> getMap () { return UnsafeCast.unsafeCast(info); } final boolean getBool () { return bool; } public final Node getGlobalNode () { if (getBool()) { return ((NGlobal)getNode()).getLeafNode(); } else { return new NGlobal ((NGlobal)getNode()); } } public void reset (Object o) {} /** * Write this Instruction instance to the RecordOutputStream. * @param s * @throws IOException */ public void write (RecordOutputStream s) throws IOException { s.startRecord (ModuleSerializationTags.G_INSTRUCTION, serializationSchema); s.writeInt (tag); s.writeBoolean (bool); s.writeInt (m); s.writeInt (n); s.writeBoolean(name != null); if (name != null) { s.writeQualifiedName(name); } s.writeBoolean (info != null); if (info != null) { writeInfo (s); } s.endRecord (); } /** * Write out the info object based on the actual type. * @param s * @throws IOException */ private void writeInfo (RecordOutputStream s) throws IOException { switch (tag) { case T_ForeignFunctionCall: { // The ForeignFunctionInfo instance is saved as a qualified name // which can be used for a lookup into the ModuleTypeInfo at // load time. ForeignFunctionInfo ffi = (ForeignFunctionInfo)info; // CAL name of the foreign function s.writeQualifiedName(ffi.getCalName()); } break; case T_Instrument: { if (!(info instanceof Executor.CallCountInfo)) { throw new IOException ("Unexpected type " + info.getClass().getName() + " encountered in I_Instrument instruction."); } Executor.CallCountInfo cci = (Executor.CallCountInfo)info; s.writeQualifiedName(cci.getName()); s.writeUTF(cci.getType()); } break; case T_LazyRecordSelection: { if (!(info instanceof String)) { throw new IOException ("Unexpected type encountered in I_LazyRecordSelection: " + info.getClass().getName()); } s.writeUTF ((String)info); } break; case T_Println: { if (!(info instanceof String)) { throw new IOException ("Unexpected type encountered in I_Println: " + info.getClass().getName()); } s.writeUTF ((String)info); } break; case T_PushGlobal: { if (!(info instanceof QualifiedName)) { throw new IOException ("Unexpected type encountered in I_PushGlobal: " + info.getClass().getName()); } s.writeQualifiedName(((QualifiedName)info)); } break; case T_PushVVal: { if (!(info instanceof NVal)) { throw new IOException ("Unexpected type encountered in I_PushVVal: " + info.getClass().getName()); } if (info instanceof NValBoolean) { s.writeUTF("boolean"); s.writeBoolean(((NValBoolean)info).getBooleanValue()); } else if (info instanceof NValChar) { s.writeUTF("char"); s.writeChar (((NValChar)info).getCharValue()); } else if (info instanceof NValDouble) { s.writeUTF("double"); s.writeDouble (((NValDouble)info).getDoubleValue()); } else if (info instanceof NValInt) { s.writeUTF("int"); s.writeInt (((NValInt)info).getIntValue()); } else if (info instanceof NValLong) { s.writeUTF("long"); s.writeLong (((NValLong)info).getLongValue()); } else if (info instanceof NValShort) { s.writeUTF("short"); s.writeShort (((NValShort)info).getShortValue()); } else if (info instanceof NValByte) { s.writeUTF("byte"); s.writeByte (((NValByte)info).getByteValue()); } else if (info instanceof NValFloat) { s.writeUTF("float"); s.writeFloat (((NValFloat)info).getFloatValue()); } else if (info instanceof NValObject) { Object value = ((NValObject)info).getValue(); if (value instanceof String) { s.writeUTF("string"); s.writeUTF ((String)value); } else if (value instanceof BigInteger) { s.writeUTF("biginteger"); String sv = ((BigInteger)value).toString(); s.writeUTF (sv); } else { throw new IOException ("Unexpected value type in I_PushVVal: " + ((Node)info).getValue().getClass().getName()); } } else { throw new IOException ("Unexpected value type in I_PushVVal: " + info.getClass().getName()); } } break; case T_PutRecordField: { s.writeUTF ((String)info); } break; case T_RecordSelection: { s.writeUTF ((String)info); } break; case T_RemoveRecordField: { s.writeUTF ((String)info); } break; case T_SwitchJ: { Map<Object, Object> m = getMap(); s.writeInt (m.size ()); for (final Map.Entry<Object, Object> entry : m.entrySet()) { Object o = entry.getKey(); if (!(o instanceof Integer) && !(o instanceof String)) { throw new IOException ("Invalid tag type in I_SwitchJ instruction: " + o.getClass().getName()); } s.writeBoolean(o instanceof Integer); if (o instanceof Integer) { s.writeInt(((Integer)o).intValue()); } else { s.writeUTF((String)o); } Integer val = (Integer)entry.getValue(); s.writeInt(val.intValue()); } } break; case T_PushGlobalN: { // Save by name. This will need to be resolved to the node // held by the corresponding GMachineFunction at load time. s.writeQualifiedName(((NGlobal)info).getName()); } break; case T_PrimOp: { // Simply store the primop code and lookup // the object at load time. PrimOp pop = (PrimOp)info; int code = pop.getCode(); s.writeInt(code); } break; case T_PackCons: case T_PackCons0: case T_PackCons2: { // We save the data constructor by name. DataConstructor dc = (DataConstructor)info; s.writeQualifiedName(dc.getName()); } break; default: if (info != null) { throw new IOException ("Unexpected instruction tag " + tag + " saving instruction info."); } break; } } /** * Unwind * */ private static class I_IUnwind extends Instruction { /** * Construct from k. */ I_IUnwind () { super (T_Unwind); } /** * Provide description of instruction. */ @Override public String toString() { return "I_Unwind"; } /** * Provide description of instruction with indent threading. */ @Override public String toString(int indent) { StringBuilder is = new StringBuilder(); for (int i = 0; i < indent; ++i) { is.append(" "); } return is.toString() + toString(); } } /** * Slide n * */ static class I_Slide extends Instruction { /** * Construct from n. */ I_Slide (int n) { super (T_Slide, n); } /** * Provide description of instruction. */ @Override public String toString() { return "I_Slide <" + getN() + ">"; } /** * Provide description of instruction with indent threading. */ @Override public String toString(int indent) { StringBuilder is = new StringBuilder(); for (int i = 0; i < indent; ++i) { is.append(" "); } return is.toString() + toString(); } } /** * Jump n. * */ static class I_Jump extends Instruction { /** * Default Constructor. */ I_Jump (int n) { super (T_Jump, n); } /** * Provide description of instruction. */ @Override public String toString() { return "I_Jump <" + getN() + ">"; } /** * Provide description of instruction with indent threading. */ @Override public String toString(int indent) { StringBuilder is = new StringBuilder(); for (int i = 0; i < indent; ++i) { is.append(" "); } return is.toString() + toString(); } } /** * MkapN n * */ static class I_MkapN extends Instruction { /** * Default Constructor. */ I_MkapN () { super (T_MkapN, 1); } /** * Construct from n. */ I_MkapN (int n) { super (T_MkapN, n); } /** * Provide description of instruction. */ @Override public String toString() { return "I_MkapN <" + getN() + ">"; } /** * Provide description of instruction with indent threading. */ @Override public String toString(int indent) { StringBuilder is = new StringBuilder(); for (int i = 0; i < indent; ++i) { is.append(" "); } return is.toString() + toString(); } } /** * PushGlobalN * Pushes a global sc fetched by index. * */ static class I_PushGlobalN extends Instruction { /** * Construct from Code. */ I_PushGlobalN (NGlobal node, boolean safe) { super (T_PushGlobalN, node, safe); } /** * Provide description of instruction. */ @Override public String toString() { String s = getNode().toString (); return "I_PushGlobalN <" + s + ">"; } /** * Provide description of instruction with indent threading. */ @Override public String toString(int indent) { StringBuilder is = new StringBuilder(); for (int i = 0; i < indent; ++i) { is.append(" "); } return is.toString() + toString(); } } /** * PushPrimitiveNode * Pushes a primitive node. * */ static class I_PushPrimitiveNode extends Instruction { /** * Construct from Code. */ I_PushPrimitiveNode (NPrimitiveFunc node) { super (T_PushPrimitiveNode, node); } /** * Provide description of instruction. */ @Override public String toString() { String s = getNode().toString (); return "I_PushPrimitiveNode <" + s + ">"; } /** * Provide description of instruction with indent threading. */ @Override public String toString(int indent) { StringBuilder is = new StringBuilder(); for (int i = 0; i < indent; ++i) { is.append(" "); } return is.toString() + toString(); } } /** * Push N * */ static class I_Push extends Instruction { /** * Construct from n. */ I_Push (int n) { super (T_Push, n); } /** * Provide description of instruction. */ @Override public String toString() { return "I_Push <" + getN() + ">"; } /** * Provide description of instruction with indent threading. */ @Override public String toString(int indent) { StringBuilder is = new StringBuilder(); for (int i = 0; i < indent; ++i) { is.append(" "); } return is.toString() + toString(); } } /** * PushGlobal S * */ static class I_PushGlobal extends Instruction { /** * Construct from n. */ I_PushGlobal (QualifiedName name) { super (T_PushGlobal, name); } /** * Provide description of instruction. */ @Override public String toString() { return "I_PushGlobal <" + getName() + ">"; } /** * Provide description of instruction with indent threading. */ @Override public String toString(int indent) { StringBuilder is = new StringBuilder(); for (int i = 0; i < indent; ++i) { is.append(" "); } return is.toString() + toString(); } } /** * PUSHVVAL. * Push the given object value directly onto the value stack. */ static class I_PushVVal extends Instruction { static I_PushVVal makePushVVal(Object v) { Node node = null; if (v instanceof Node) { node = (Node) v; } else if (v instanceof Character) { node = new NValChar(((Character) v).charValue()); } else if (v instanceof Double) { node = new NValDouble(((Double) v).doubleValue()); } else if (v instanceof Integer) { node = new NValInt(((Integer) v).intValue()); } else if (v instanceof Long) { node = new NValLong(((Long) v).longValue()); } else if (v instanceof Short) { node = new NValShort(((Short) v).shortValue()); } else if (v instanceof Byte) { node = new NValByte(((Byte) v).byteValue()); } else if (v instanceof Float) { node = new NValFloat(((Float) v).floatValue()); } else if (v instanceof Boolean) { node = new NValBoolean(((Boolean)v).booleanValue()); } else { node = new NValObject(v); } return new I_PushVVal(node); } /** * Construct from value object. */ private I_PushVVal(Node node) { super (T_PushVVal, node); } /** * Provide description of instruction. */ @Override public String toString() { return "I_PushVVal <" + getNode() + ">"; } /** * Provide description of instruction with indent threading. */ @Override public String toString(int indent) { StringBuilder is = new StringBuilder(); for (int i = 0; i < indent; ++i) { is.append(" "); } return is + toString(); } } /** * PUSHVVAL. * Push the given object value directly onto the value stack. */ private static class I_IPushTrue extends Instruction { /** * Construct from value object. */ I_IPushTrue (){ super (T_PushTrue); } /** * Provide description of instruction. */ @Override public String toString() { return "I_PushTrue <>"; } /** * Provide description of instruction with indent threading. */ @Override public String toString(int indent) { StringBuilder is = new StringBuilder(); for (int i = 0; i < indent; ++i) { is.append(" "); } return is + toString(); } } /** * PUSHVVAL. * Push the given object value directly onto the value stack. */ private static class I_IPushFalse extends Instruction { /** * Construct from value object. */ I_IPushFalse (){ super (T_PushFalse); } /** * Provide description of instruction. */ @Override public String toString() { return "I_PushFalse <>"; } /** * Provide description of instruction with indent threading. */ @Override public String toString(int indent) { StringBuilder is = new StringBuilder(); for (int i = 0; i < indent; ++i) { is.append(" "); } return is + toString(); } } /** * UPDATE n. * Overwite the (n + 1) stack item with an indirection to the top stack item. */ static class I_Update extends Instruction { /** * Construct from value object. */ I_Update (int n) { super (T_Update, n); } /** * Provide description of instruction. */ @Override public String toString() { return "I_Update <" + getN() + ">"; } /** * Provide description of instruction with indent threading. */ @Override public String toString(int indent) { StringBuilder is = new StringBuilder(); for (int i = 0; i < indent; ++i) { is.append(" "); } return is + toString(); } } static class I_Println extends Instruction { /** * Construct from value object. */ I_Println (String s) { super (T_Println, s); } /** * Provide description of instruction. */ @Override public String toString() { return "I_Println <" + getInfo() + ">"; } /** * Provide description of instruction with indent threading. */ @Override public String toString(int indent) { StringBuilder is = new StringBuilder(); for (int i = 0; i < indent; ++i) { is.append(" "); } return is + toString(); } } /** * POP n. * Pop n items off the stack. */ static class I_Pop extends Instruction { /** * Construct from value object. */ I_Pop (int n) { super (T_Pop, n); } /** * Provide description of instruction. */ @Override public String toString() { return "I_Pop <" + getN() + ">"; } /** * Provide description of instruction with indent threading. */ @Override public String toString(int indent) { StringBuilder is = new StringBuilder(); for (int i = 0; i < indent; ++i) { is.append(" "); } return is + toString(); } } /** * Instrument. * Instrument the code stream with an arbitary object. */ static class I_Instrument extends Instruction { /** * Construct from instrumenting object. */ I_Instrument(Object object) { super (T_Instrument, object); } /** * Provide description of instruction. */ @Override public String toString() { return "I_Instrument <" + getInfo() + ">"; } /** * Provide description of instruction with indent threading. */ @Override public String toString(int indent) { StringBuilder is = new StringBuilder(); for (int i = 0; i < indent; ++i) { is.append(" "); } return is + toString(); } } /** * Instrument. * Instrument the code stream with an arbitary object. */ static class I_Alloc extends Instruction { /** * Construct from instrumenting object. */ I_Alloc (int n) { super (T_Alloc, n); } /** * Provide description of instruction. */ @Override public String toString() { return "I_Alloc <" + getN() + ">"; } /** * Provide description of instruction with indent threading. */ @Override public String toString(int indent) { StringBuilder is = new StringBuilder(); for (int i = 0; i < indent; ++i) { is.append(" "); } return is + toString(); } } /** * Eval * Force the strict evaluation of an expression. */ private static class I_IEval extends Instruction { /** * Construct from instrumenting object. */ I_IEval () { super (T_Eval); } /** * Provide description of instruction. */ @Override public String toString() { return "I_Eval"; } /** * Provide description of instruction with indent threading. */ @Override public String toString(int indent) { StringBuilder is = new StringBuilder(); for (int i = 0; i < indent; ++i) { is.append(" "); } return is + toString(); } } /** * Cond. * Peform a conditional branch. */ static class I_Cond extends Instruction { private Code c1; private Code c2; /** * Construct from instrumenting object. */ I_Cond (Code c1, Code c2) { super (T_Cond); this.c1 = c1; this.c2 = c2; } public Code getTrueCode () { return c1; } public void setTrueCode (Code c) { this.c1 = c; } public Code getFalseCode () { return c2; } public void setFalseCode (Code c) { this.c2 = c; } /** * Provide description of instruction. */ @Override public String toString() { return toString (0); } /** * Provide description of instruction with indent threading. */ @Override public String toString(int indent) { StringBuilder is = new StringBuilder(); for (int i = 0; i < indent; ++i) { is.append(" "); } StringBuilder sb = new StringBuilder (); sb.append(is); sb.append("I_Cond\n"); sb.append(is + " Branch 1:\n"); sb.append (c1.toString (indent + 4)); sb.append (is + " Branch 2:\n"); sb.append (c2.toString (indent + 4)); return sb.toString (); } } /** * CondJ. * Peform a conditional jump. */ static class I_CondJ extends Instruction { /** * Construct from instrumenting object. */ I_CondJ (int n) { super (T_CondJ, n); } /** * Provide description of instruction. */ @Override public String toString() { return toString (0); } /** * Provide description of instruction with indent threading. */ @Override public String toString(int indent) { StringBuilder is = new StringBuilder(); for (int i = 0; i < indent; ++i) { is.append(" "); } StringBuilder sb = new StringBuilder (); sb.append(is); sb.append("I_CondJ <" + getN() + ">"); return sb.toString (); } } /** * PrimOp. * Perform a primitive operation on the value stack. */ static class I_PrimOp extends Instruction { /** * Construct from PrimOp sub-code. */ I_PrimOp(int subCode) { super (T_PrimOp, PrimOp.getPrimOpForCode (subCode).getArity(), PrimOp.getPrimOpForCode (subCode)); } /** * Provide description of instruction. */ @Override public String toString() { return "I_PrimOp <" + ((PrimOp)getInfo()).getDescription () + ">"; } /** * Provide description of instruction with indent threading. */ @Override public String toString(int indent) { StringBuilder is = new StringBuilder(); for (int i = 0; i < indent; ++i) { is.append(" "); } return is + toString(); } } /** * I_PackCons. */ static class I_PackCons extends Instruction { private I_PackCons(DataConstructor dataConstructor) { super (T_PackCons, dataConstructor.getArity(), dataConstructor.getOrdinal(), dataConstructor, dataConstructor.getName()); } static Instruction makePackCons(DataConstructor dc) { int arity = dc.getArity (); Instruction instruction; if (arity == 0) { if (dc.getName().equals(CAL_Prelude.DataConstructors.True)) { instruction = I_PushVVal.makePushVVal(Boolean.TRUE); } else if (dc.getName().equals(CAL_Prelude.DataConstructors.False)) { instruction = I_PushVVal.makePushVVal(Boolean.FALSE); } else { instruction = new Instruction.I_PackCons0 (dc); } } else if (arity == 2) { instruction = new Instruction.I_PackCons2 (dc); } else { instruction = new Instruction.I_PackCons (dc); } return instruction; } /** * Provide description of instruction. */ @Override public String toString() { return "I_PackCons <" + getInfo() + ", " + getOrd() + ", " + getArity() + ">"; } /** * Provide description of instruction with indent threading. */ @Override public String toString(int indent) { StringBuilder is = new StringBuilder(); for (int i = 0; i < indent; ++i) { is.append(" "); } return is + toString(); } } /** * I_PackCons0. */ static class I_PackCons0 extends Instruction { private I_PackCons0(DataConstructor dataConstructor) { super (T_PackCons0, 0, dataConstructor.getOrdinal(), dataConstructor, dataConstructor.getName()); if (dataConstructor.getArity() != 0) { throw new IllegalArgumentException ("the arity of the dataConstructor must be 0."); } } /** * Provide description of instruction. */ @Override public String toString() { return "I_PackCons0 <" + getInfo() + ", " + getOrd() + ">"; } /** * Provide description of instruction with indent threading. */ @Override public String toString(int indent) { StringBuilder is = new StringBuilder(); for (int i = 0; i < indent; ++i) { is.append(" "); } return is + toString(); } } /** * I_PackCons2. */ static class I_PackCons2 extends Instruction { private I_PackCons2(DataConstructor dataConstructor) { super (T_PackCons2, 2, dataConstructor.getOrdinal(), dataConstructor, dataConstructor.getName()); if (dataConstructor.getArity() != 2) { throw new IllegalArgumentException ("the arity of the dataConstructor must be 2."); } } /** * Provide description of instruction. */ @Override public String toString() { return "I_PackCons2 <" + getInfo() + ", " + getOrd() + ", " + 2 + ">"; } /** * Provide description of instruction with indent threading. */ @Override public String toString(int indent) { StringBuilder is = new StringBuilder(); for (int i = 0; i < indent; ++i) { is.append(" "); } return is + toString(); } } /** * SWITCH cs. * Jump to the evaluation of some code from several alternatives. */ static class I_Switch extends Instruction { // Information about the position in the source of the case statement to // be used to augment error messages. This may be null. private final ErrorInfo errorInfo; /** * Construct. */ I_Switch(Map<Object, Code> codesMap, ErrorInfo errorInfo) { super (T_Switch, codesMap); this.errorInfo = errorInfo; } /** * @return The error info to provide the user with for error situations. */ ErrorInfo getErrorInfo(){ return errorInfo; } /** * Provide description of instruction. */ @Override public String toString() { return toString(0); } /** * Provide description of instruction with indent threading. */ @Override public String toString(int indent) { StringBuilder is = new StringBuilder(); for (int i = 0; i < indent; ++i) { is.append(" "); } StringBuilder sb = new StringBuilder(); sb.append(is + "I_Switch <\n"); java.util.Iterator<Object> keysIterator = getMap().keySet().iterator(); while (keysIterator.hasNext()) { Object altTag = keysIterator.next(); sb.append (is + " " + altTag.toString() + " ->\n"); sb.append(((Code) getMap().get(altTag)).toString(indent + 4)); sb.append ("\n"); } sb.append(is + ">"); return sb.toString(); } } /** * SWITCH cs. * Jump to the evaluation of some code from several alternatives. */ static class I_SwitchJ extends Instruction { // Information about the position in the source of the case statement to // be used to augment error messages. This may be null. private final ErrorInfo errorInfo; /** * Construct. */ I_SwitchJ(Map<Object, Integer> jumpMap, ErrorInfo errorInfo) { super (T_SwitchJ, jumpMap); this.errorInfo = errorInfo; } /** * @return The error info to provide the user with for error situations. */ ErrorInfo getErrorInfo(){ return errorInfo; } /** * Provide description of instruction. */ @Override public String toString() { return toString(0); } /** * Provide description of instruction with indent threading. */ @Override public String toString(int indent) { StringBuilder is = new StringBuilder(); for (int i = 0; i < indent; ++i) { is.append(" "); } StringBuilder sb = new StringBuilder(); sb.append(is + "I_Switch <\n"); java.util.Iterator<?> keysIterator = getMap().keySet().iterator(); while (keysIterator.hasNext()) { Object altTag = keysIterator.next(); Integer jump = (Integer)getMap().get (altTag); sb.append (is + " " + altTag.toString() + " -> " + jump + "\n"); } sb.append(is + ">"); return sb.toString(); } } /** * SelectDCField. * Pop the DC node off the stack, and push the value of the dc field. */ static class I_SelectDCField extends Instruction { /** * Information about the position in the source of the case statement to be used to augment error messages. * This may be null. */ private final ErrorInfo errorInfo; /** * Constructor for a I_SelectDCField. * @param dataConstructor the expected data constructor. * @param fieldIndex the index of the desired field. * @param errorInfo error info for the source position of the selection. */ I_SelectDCField(DataConstructor dataConstructor, int fieldIndex, ErrorInfo errorInfo) { super (T_SelectDCField, fieldIndex, dataConstructor); this.errorInfo = errorInfo; } /** * @return The error info to provide the user with for error situations. */ ErrorInfo getErrorInfo(){ return errorInfo; } /** * Provide description of instruction. */ @Override public String toString() { return toString(0); } /** * Provide description of instruction with indent threading. */ @Override public String toString(int indent) { StringBuilder is = new StringBuilder(); for (int i = 0; i < indent; ++i) { is.append(" "); } return is + "I_SelectDCField <" + ((DataConstructor)getInfo()).getName() + ", " + getN() + ">"; } } /** * SelectDCField. * Pop the DC node off the stack, and push the value of the dc field. */ static class I_LazySelectDCField extends Instruction { /** * Information about the position in the source of the case statement to be used to augment error messages. * This may be null. */ private final ErrorInfo errorInfo; /** * Constructor for a I_SelectDCField. * @param dataConstructor the expected data constructor. * @param fieldIndex the index of the desired field. * @param errorInfo error info for the source position of the selection. */ I_LazySelectDCField(DataConstructor dataConstructor, int fieldIndex, ErrorInfo errorInfo) { super (T_LazySelectDCField, fieldIndex, dataConstructor); this.errorInfo = errorInfo; } /** * @return The error info to provide the user with for error situations. */ ErrorInfo getErrorInfo(){ return errorInfo; } /** * Provide description of instruction. */ @Override public String toString() { return toString(0); } /** * Provide description of instruction with indent threading. */ @Override public String toString(int indent) { StringBuilder is = new StringBuilder(); for (int i = 0; i < indent; ++i) { is.append(" "); } return is + "I_LazySelectDCField <" + ((DataConstructor)getInfo()).getName() + ", " + getN() + ">"; } } /** * Split */ static class I_Split extends Instruction { /** * Construct. */ I_Split (int n) { super (T_Split, n); } /** * Provide description of instruction. */ @Override public String toString() { return toString(0); } /** * Provide description of instruction with indent threading. */ @Override public String toString(int indent) { StringBuilder is = new StringBuilder(); for (int i = 0; i < indent; ++i) { is.append(" "); } return is + "I_Split <" + getN() + ">"; } } /** * Instruction for calling foreign functions. At this point, it is rather similar to I_PrimOp * but will evolve as non-simple types are allowed for arguments and return types. */ static class I_ForeignFunctionCall extends Instruction { /** * @param foreignSCInfo ForeignFunctionInfo */ I_ForeignFunctionCall(ForeignFunctionInfo foreignSCInfo) { super (T_ForeignFunctionCall, foreignSCInfo); } /** * Provide description of instruction. */ @Override public String toString() { return "I_ForeignFunctionCall <" + getInfo() + ">"; } /** * Provide description of instruction with indent threading */ @Override public String toString(int indent) { StringBuilder is = new StringBuilder(); for (int i = 0; i < indent; ++i) { is.append(" "); } return is + toString(); } } /** * ClearStack. * Empty the machines stack. This is used in the event of a programmatic error. */ private static class I_IClearStack extends Instruction { /** * Construct from listener. */ I_IClearStack () { super (T_ClearStack); } /** * Provide description of instruction. */ @Override public String toString() { return "I_ClearStack"; } /** * Provide description of instruction with indent threading. */ @Override public String toString(int indent) { StringBuilder is = new StringBuilder(); for (int i = 0; i < indent; ++i) { is.append(" "); } return is + toString(); } } /** * Dispatch n. * Performs case analysis on the function on the top of the stack and * enters it in an appropriate manner. */ static class I_Dispatch extends Instruction { /** * Construct from an integer. */ I_Dispatch (int n) { super (T_Dispatch, n); } /** * Provide description of instruction. */ @Override public String toString() { StringBuilder sb = new StringBuilder (); sb.append ("I_Dispatch<" + getN() + ">"); return sb.toString (); } /** * Provide description of instruction with indent threading. */ @Override public String toString(int indent) { StringBuilder is = new StringBuilder(); for (int i = 0; i < indent; ++i) { is.append(" "); } return is + toString(); } } /** * Call n. * Allocates a root then performs case analysis on the function on the top of the stack and * enters it in an appropriate manner. */ static class I_Call extends Instruction { /** * Construct from an integer. */ I_Call (int n) { super (T_Call, n); } /** * Provide description of instruction. */ @Override public String toString() { StringBuilder sb = new StringBuilder (); sb.append ("I_Call<" + getN() + ">"); return sb.toString (); } /** * Provide description of instruction with indent threading. */ @Override public String toString(int indent) { StringBuilder is = new StringBuilder(); for (int i = 0; i < indent; ++i) { is.append(" "); } return is + toString(); } } /** * Squeeze x y. * Slide down the top x elements on the stack squeezing out the y elements below. */ static class I_Squeeze extends Instruction { /** * Construct from an integer. */ I_Squeeze (int x, int y) { super (T_Squeeze, x, y); } /** * Provide description of instruction. */ @Override public String toString() { StringBuilder sb = new StringBuilder (); sb.append ("I_Squeeze<" + getX() + ", " + getY() + ">"); return sb.toString (); } /** * Provide description of instruction with indent threading. */ @Override public String toString(int indent) { StringBuilder is = new StringBuilder(); for (int i = 0; i < indent; ++i) { is.append(" "); } return is + toString(); } } /** * I_CreateRecord: instruction to create a new record object. * @author RCypher * Created: Apr 12, 2004 */ static class I_CreateRecord extends Instruction { /** * Construct from an field map. */ I_CreateRecord (int nFields) { super (T_CreateRecord, nFields); } /** * Provide description of instruction with indent threading. */ @Override public String toString(int indent) { StringBuilder is = new StringBuilder(); for (int i = 0; i < indent; ++i) { is.append(" "); } StringBuilder out = new StringBuilder(); out.append (is); out.append ("I_CreateRecord<" + getN() + ">\n"); return out.toString(); } @Override public String toString () { return toString (0); } } /** * Place a field value in the record on top of the stack. * I_PutRecordField * @author RCypher * Created: Apr 13, 2004 */ static class I_PutRecordField extends Instruction { I_PutRecordField (String fieldName) { super (T_PutRecordField, fieldName); } /** * Provide description of instruction with indent threading. */ @Override public String toString(int indent) { StringBuilder is = new StringBuilder(); for (int i = 0; i < indent; ++i) { is.append(" "); } StringBuilder out = new StringBuilder(); out.append (is); out.append ("I_SetRecordField<" + getInfo().toString() + ">\n"); return out.toString(); } @Override public String toString () { return toString (0); } } /** * Remove a field value from the record on top of the stack. * I_RemoveRecordField * @author RCypher * Created: Apr 13, 2004 */ static class I_RemoveRecordField extends Instruction { I_RemoveRecordField (String fieldName) { super (T_RemoveRecordField, fieldName); } /** * Provide description of instruction with indent threading. */ @Override public String toString(int indent) { StringBuilder is = new StringBuilder(); for (int i = 0; i < indent; ++i) { is.append(" "); } StringBuilder out = new StringBuilder(); out.append (is); out.append ("I_RemoveRecordField<" + getInfo().toString() + ">\n"); return out.toString(); } @Override public String toString () { return toString (0); } } /** * Extend the record value on top of the stack. * I_ExtendRecord * @author RCypher * Created: Apr 13, 2004 */ static class I_ExtendRecord extends Instruction { I_ExtendRecord () { super (T_ExtendRecord); } @Override public String toString (int indent) { StringBuilder is = new StringBuilder(); for (int i = 0; i < indent; ++i) { is.append(" "); } return is + "I_ExtendRecord<>"; } @Override public String toString () { return toString (0); } } /** * Select the named field value from the record * on top of the stack. * I_RecordSelection * @author RCypher * Created: Apr 13, 2004 */ static class I_RecordSelection extends Instruction { I_RecordSelection (String fieldName) { super (T_RecordSelection, fieldName); } @Override public String toString (int indent) { StringBuilder is = new StringBuilder(); for (int i = 0; i < indent; ++i) { is.append(" "); } return is + "I_RecordSelection<" + getInfo().toString() + ">"; } @Override public String toString () { return toString (0); } } /** * Creates a node representing the application of a virtual * record selection function to the record value on the * top of the stack. * I_LazyRecordSelection * @author RCypher * Created: Apr 13, 2004 */ static class I_LazyRecordSelection extends Instruction { I_LazyRecordSelection (String fieldName) { super (T_LazyRecordSelection, fieldName); } @Override public String toString (int indent) { StringBuilder is = new StringBuilder(); for (int i = 0; i < indent; ++i) { is.append(" "); } return is + "I_LazyRecordSelection<" + getInfo().toString() + ">"; } @Override public String toString () { return toString (0); } } /** * Creates a node representing an application of a virtual record * extension function to the record value on the top of the stack. * I_LazyRecordExtension * @author Bo Ilic * Created: May 4, 2006 */ static class I_LazyRecordUpdate extends Instruction { I_LazyRecordUpdate () { super (T_LazyRecordUpdate); } @Override public String toString (int indent) { StringBuilder is = new StringBuilder(); for (int i = 0; i < indent; ++i) { is.append(" "); } return is + "I_LazyRecordUpdate<>"; } @Override public String toString () { return toString (0); } } /** * Creates a node representing an application of a virtual record * extension function to the record value on the top of the stack. * I_LazyRecordExtension * @author RCypher * Created: Apr 13, 2004 */ static class I_LazyRecordExtension extends Instruction { I_LazyRecordExtension () { super (T_LazyRecordExtension); } @Override public String toString (int indent) { StringBuilder is = new StringBuilder(); for (int i = 0; i < indent; ++i) { is.append(" "); } return is + "I_LazyRecordExtension<>"; } @Override public String toString () { return toString (0); } } /** * Create a java list object and push it onto the stack in an NValObject node. * @author RCypher */ static class I_CreateList extends Instruction { I_CreateList () { super (T_CreateList); } @Override public String toString (int indent) { StringBuilder is = new StringBuilder(); for (int i = 0; i < indent; ++i) { is.append(" "); } is.append("I_CreateList<>"); return is.toString(); } @Override public String toString () { return toString (0); } } /** * Push the opaque value in an NValObject node on the top of the stack into * the list immediately above it. * @author RCypher */ static class I_PutListValue extends Instruction { I_PutListValue () { super (T_PutListValue); } @Override public String toString (int indent) { StringBuilder is = new StringBuilder(); for (int i = 0; i < indent; ++i) { is.append(" "); } is.append("I_PutListValue<>"); return is.toString(); } @Override public String toString () { return toString (0); } } /** * Ensure the opaque value in an NValObject can be cast to the given type. * @author RCypher */ static class I_Cast extends Instruction { I_Cast (Class<?> castType) { super (T_Cast, castType); } @Override public String toString(int indent) { StringBuilder is = new StringBuilder(); for (int i = 0; i < indent; ++i) { is.append(" "); } is.append("I_Cast<" + ((Class<?>)getInfo()).getName() + ">"); return is.toString(); } @Override public String toString() {return toString(0);} } /** * Generate a trace message for the currently executing function. * @author rcypher */ static final class I_Debug_Processing extends Instruction { // We want to hold the name of the function and the // arity. This lets us generate a trace message // with the name of the function and the state of the // argument values. I_Debug_Processing (QualifiedName name, int arity) { super (T_DebugProcessing, arity, name); } @Override public String toString(int indent) { StringBuilder is = new StringBuilder(); for (int i = 0; i < indent; ++i) { is.append(" "); } is.append("I_Debug_Processing <" + getName() + ">"); return is.toString(); } @Override public String toString() {return toString(0);} } }