// NOTE when arg is an array, this method will corrupt the two registers adjacent to target_reg // "corrupt" in the sense of any value being there previousvly will be lost // this should be taken into account by methods that call this method // also this was not tested with nested arrays, might work, might not work yet private static void LoadIntoReg(ScriptBuilder sb, byte target_reg, object arg) { if (arg is string) { sb.EmitLoad(target_reg, (string)arg); } else if (arg is int) { sb.EmitLoad(target_reg, new BigInteger((int)arg)); } else if (arg is long) { sb.EmitLoad(target_reg, new BigInteger((long)arg)); } else if (arg is BigInteger) { sb.EmitLoad(target_reg, (BigInteger)arg); } else if (arg is bool) { sb.EmitLoad(target_reg, (bool)arg); } else if (arg is byte[]) { sb.EmitLoad(target_reg, (byte[])arg, VMType.Bytes); } else if (arg is Enum) { sb.EmitLoad(target_reg, (Enum)arg); } else if (arg is Timestamp) { sb.EmitLoad(target_reg, (Timestamp)arg); } else if (arg is ISerializable) { sb.EmitLoad(target_reg, (ISerializable)arg); } else { var srcType = arg.GetType(); if (srcType.IsArray) { // this cast is required to clear any previous value that might be stored at target_reg sb.Emit(Opcode.CAST, new byte[] { target_reg, target_reg, (byte)VMType.None }); var array = (Array)arg; for (int j = 0; j < array.Length; j++) { var element = array.GetValue(j); byte temp_regVal = (byte)(target_reg + 1); byte temp_regKey = (byte)(target_reg + 2); LoadIntoReg(sb, temp_regVal, element); LoadIntoReg(sb, temp_regKey, j); sb.Emit(Opcode.PUT, new byte[] { temp_regVal, target_reg, temp_regKey }); } } else { throw new System.Exception("invalid type: " + srcType.Name); } } }
public static byte[] EndScript(this ScriptBuilder sb) { sb.Emit(VM.Opcode.RET); return(sb.ToScript()); }