|
|
@@ -1,5 +1,6 @@
|
|
|
using System;
|
|
|
using System.Collections.Generic;
|
|
|
+using System.IO;
|
|
|
using System.Linq;
|
|
|
using System.Text;
|
|
|
using MoonSharp.Interpreter.Debugging;
|
|
|
@@ -8,86 +9,50 @@ namespace MoonSharp.Interpreter.Execution.VM
|
|
|
{
|
|
|
internal class Instruction
|
|
|
{
|
|
|
- public OpCode OpCode;
|
|
|
- public SymbolRef Symbol;
|
|
|
- public SymbolRef[] SymbolList;
|
|
|
- public string Name;
|
|
|
- public DynValue Value;
|
|
|
- public int NumVal;
|
|
|
- public int NumVal2;
|
|
|
- public SourceRef SourceCodeRef;
|
|
|
-
|
|
|
- public Instruction(SourceRef sourceref)
|
|
|
+ internal OpCode OpCode;
|
|
|
+ internal SymbolRef Symbol;
|
|
|
+ internal SymbolRef[] SymbolList;
|
|
|
+ internal string Name;
|
|
|
+ internal DynValue Value;
|
|
|
+ internal int NumVal;
|
|
|
+ internal int NumVal2;
|
|
|
+ internal SourceRef SourceCodeRef;
|
|
|
+
|
|
|
+ internal Instruction(SourceRef sourceref)
|
|
|
{
|
|
|
SourceCodeRef = sourceref;
|
|
|
}
|
|
|
|
|
|
public override string ToString()
|
|
|
{
|
|
|
- string append = "";
|
|
|
+ string append = this.OpCode.ToString().ToUpperInvariant();
|
|
|
|
|
|
- switch (OpCode)
|
|
|
- {
|
|
|
- case OpCode.Closure:
|
|
|
- append = string.Format("{0}{1:X8}({2})", GenSpaces(), NumVal, string.Join(",", SymbolList.Select(s => s.ToString()).ToArray()));
|
|
|
- break;
|
|
|
- case OpCode.Args:
|
|
|
- append = string.Format("{0}({1})", GenSpaces(), string.Join(",", SymbolList.Select(s => s.ToString()).ToArray()));
|
|
|
- break;
|
|
|
- case OpCode.Debug:
|
|
|
- return string.Format("[[ {0} ]]", Name);
|
|
|
- case OpCode.Literal:
|
|
|
- case OpCode.Index:
|
|
|
- append = string.Format("{0}{1}", GenSpaces(), PurifyFromNewLines(Value));
|
|
|
- break;
|
|
|
- case OpCode.IndexSet:
|
|
|
- append = string.Format("{0}{1} <- {2}:{3}", GenSpaces(), PurifyFromNewLines(Value), NumVal, NumVal2);
|
|
|
- break;
|
|
|
- case OpCode.Nop:
|
|
|
- append = string.Format("{0}#{1}", GenSpaces(), Name);
|
|
|
- break;
|
|
|
- case OpCode.Call:
|
|
|
- case OpCode.Ret:
|
|
|
- case OpCode.MkTuple:
|
|
|
- case OpCode.ExpTuple:
|
|
|
- case OpCode.Incr:
|
|
|
- case OpCode.Pop:
|
|
|
- case OpCode.Copy:
|
|
|
- append = string.Format("{0}{1}", GenSpaces(), NumVal);
|
|
|
- break;
|
|
|
- case OpCode.Enter:
|
|
|
- case OpCode.Leave:
|
|
|
- case OpCode.Exit:
|
|
|
- case OpCode.Swap:
|
|
|
- append = string.Format("{0}{1},{2}", GenSpaces(), NumVal, NumVal2);
|
|
|
- break;
|
|
|
- case OpCode.BeginFn:
|
|
|
- append = string.Format("{0}{1}:{2},{3}", GenSpaces(), Name, NumVal, NumVal2);
|
|
|
- break;
|
|
|
- case OpCode.Local:
|
|
|
- case OpCode.Upvalue:
|
|
|
- append = string.Format("{0}{1}", GenSpaces(), Symbol);
|
|
|
- break;
|
|
|
- case OpCode.StoreUpv:
|
|
|
- case OpCode.StoreLcl:
|
|
|
- append = string.Format("{0}{1} <- {2}:{3}", GenSpaces(), Symbol, NumVal, NumVal2);
|
|
|
- break;
|
|
|
- case OpCode.JtOrPop:
|
|
|
- case OpCode.JfOrPop:
|
|
|
- case OpCode.Jf:
|
|
|
- case OpCode.Jump:
|
|
|
- case OpCode.JFor:
|
|
|
- case OpCode.JNil:
|
|
|
- append = string.Format("{0}{1:X8}", GenSpaces(), NumVal);
|
|
|
- break;
|
|
|
- case OpCode.Invalid:
|
|
|
- append = string.Format("{0}{1}", GenSpaces(), Name ?? "(null)");
|
|
|
- break;
|
|
|
- default:
|
|
|
- break;
|
|
|
- }
|
|
|
+ int usage = (int)OpCode.GetFieldUsage();
|
|
|
+
|
|
|
+ if (usage != 0)
|
|
|
+ append += GenSpaces();
|
|
|
+
|
|
|
+ if ((this.OpCode == VM.OpCode.FuncMeta) ||((usage & ((int)InstructionFieldUsage.NumValAsCodeAddress)) == (int)InstructionFieldUsage.NumValAsCodeAddress))
|
|
|
+ append += " " + NumVal.ToString("X8");
|
|
|
+ else if ((usage & ((int)InstructionFieldUsage.NumVal)) != 0)
|
|
|
+ append += " " + NumVal.ToString();
|
|
|
+
|
|
|
+ if ((usage & ((int)InstructionFieldUsage.NumVal2)) != 0)
|
|
|
+ append += " " + NumVal2.ToString();
|
|
|
+
|
|
|
+ if ((usage & ((int)InstructionFieldUsage.Name)) != 0)
|
|
|
+ append += " " + Name;
|
|
|
+
|
|
|
+ if ((usage & ((int)InstructionFieldUsage.Value)) != 0)
|
|
|
+ append += " " + PurifyFromNewLines(Value);
|
|
|
|
|
|
- return this.OpCode.ToString().ToUpperInvariant() + append;
|
|
|
+ if ((usage & ((int)InstructionFieldUsage.Symbol)) != 0)
|
|
|
+ append += " " + Symbol;
|
|
|
+
|
|
|
+ if (((usage & ((int)InstructionFieldUsage.SymbolList)) != 0) && (SymbolList != null))
|
|
|
+ append += " " + string.Join(",", SymbolList.Select(s => s.ToString()).ToArray());
|
|
|
+
|
|
|
+ return append;
|
|
|
}
|
|
|
|
|
|
private string PurifyFromNewLines(DynValue Value)
|
|
|
@@ -103,7 +68,160 @@ namespace MoonSharp.Interpreter.Execution.VM
|
|
|
return new string(' ', 10 - this.OpCode.ToString().Length);
|
|
|
}
|
|
|
|
|
|
-
|
|
|
+ internal void WriteBinary(BinaryWriter wr, int baseAddress, Dictionary<SymbolRef, int> symbolMap)
|
|
|
+ {
|
|
|
+ wr.Write((byte)this.OpCode);
|
|
|
+
|
|
|
+ int usage = (int)OpCode.GetFieldUsage();
|
|
|
+
|
|
|
+ if ((usage & ((int)InstructionFieldUsage.NumValAsCodeAddress)) == (int)InstructionFieldUsage.NumValAsCodeAddress)
|
|
|
+ wr.Write(this.NumVal - baseAddress);
|
|
|
+ else if ((usage & ((int)InstructionFieldUsage.NumVal)) != 0)
|
|
|
+ wr.Write(this.NumVal);
|
|
|
+
|
|
|
+ if ((usage & ((int)InstructionFieldUsage.NumVal2)) != 0)
|
|
|
+ wr.Write(this.NumVal2);
|
|
|
+
|
|
|
+ if ((usage & ((int)InstructionFieldUsage.Name)) != 0)
|
|
|
+ wr.Write(Name);
|
|
|
+
|
|
|
+ if ((usage & ((int)InstructionFieldUsage.Value)) != 0)
|
|
|
+ DumpValue(wr, Value);
|
|
|
+
|
|
|
+ if ((usage & ((int)InstructionFieldUsage.Symbol)) != 0)
|
|
|
+ WriteSymbol(wr, Symbol, symbolMap);
|
|
|
+
|
|
|
+ if ((usage & ((int)InstructionFieldUsage.SymbolList)) != 0)
|
|
|
+ {
|
|
|
+ wr.Write(this.SymbolList.Length);
|
|
|
+ for (int i = 0; i < this.SymbolList.Length; i++)
|
|
|
+ WriteSymbol(wr, SymbolList[i], symbolMap);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private static void WriteSymbol(BinaryWriter wr, SymbolRef symbolRef, Dictionary<SymbolRef, int> symbolMap)
|
|
|
+ {
|
|
|
+ int id = (symbolRef == null) ? -1 : symbolMap[symbolRef];
|
|
|
+ wr.Write(id);
|
|
|
+ }
|
|
|
+
|
|
|
+ private static SymbolRef ReadSymbol(BinaryReader rd, SymbolRef[] deserializedSymbols)
|
|
|
+ {
|
|
|
+ int id = rd.ReadInt32();
|
|
|
+
|
|
|
+ if (id < 0) return null;
|
|
|
+ return deserializedSymbols[id];
|
|
|
+ }
|
|
|
+
|
|
|
+ internal static Instruction ReadBinary(SourceRef chunkRef, BinaryReader rd, int baseAddress, Table envTable, SymbolRef[] deserializedSymbols)
|
|
|
+ {
|
|
|
+ Instruction that = new Instruction(chunkRef);
|
|
|
|
|
|
+ that.OpCode = (OpCode)rd.ReadByte();
|
|
|
+
|
|
|
+ int usage = (int)that.OpCode.GetFieldUsage();
|
|
|
+
|
|
|
+ if ((usage & ((int)InstructionFieldUsage.NumValAsCodeAddress)) == (int)InstructionFieldUsage.NumValAsCodeAddress)
|
|
|
+ that.NumVal = rd.ReadInt32() + baseAddress;
|
|
|
+ else if ((usage & ((int)InstructionFieldUsage.NumVal)) != 0)
|
|
|
+ that.NumVal = rd.ReadInt32();
|
|
|
+
|
|
|
+ if ((usage & ((int)InstructionFieldUsage.NumVal2)) != 0)
|
|
|
+ that.NumVal2 = rd.ReadInt32();
|
|
|
+
|
|
|
+ if ((usage & ((int)InstructionFieldUsage.Name)) != 0)
|
|
|
+ that.Name = rd.ReadString();
|
|
|
+
|
|
|
+ if ((usage & ((int)InstructionFieldUsage.Value)) != 0)
|
|
|
+ that.Value = ReadValue(rd, envTable);
|
|
|
+
|
|
|
+ if ((usage & ((int)InstructionFieldUsage.Symbol)) != 0)
|
|
|
+ that.Symbol = ReadSymbol(rd, deserializedSymbols);
|
|
|
+
|
|
|
+ if ((usage & ((int)InstructionFieldUsage.SymbolList)) != 0)
|
|
|
+ {
|
|
|
+ int len = rd.ReadInt32();
|
|
|
+ that.SymbolList = new SymbolRef[len];
|
|
|
+
|
|
|
+ for (int i = 0; i < that.SymbolList.Length; i++)
|
|
|
+ that.SymbolList[i] = ReadSymbol(rd, deserializedSymbols);
|
|
|
+ }
|
|
|
+
|
|
|
+ return that;
|
|
|
+ }
|
|
|
+
|
|
|
+ private static DynValue ReadValue(BinaryReader rd, Table envTable)
|
|
|
+ {
|
|
|
+ bool isnull = !rd.ReadBoolean();
|
|
|
+
|
|
|
+ if (isnull) return null;
|
|
|
+
|
|
|
+ DataType dt = (DataType)rd.ReadByte();
|
|
|
+
|
|
|
+ switch (dt)
|
|
|
+ {
|
|
|
+ case DataType.Nil:
|
|
|
+ return DynValue.NewNil();
|
|
|
+ case DataType.Void:
|
|
|
+ return DynValue.Void;
|
|
|
+ case DataType.Boolean:
|
|
|
+ return DynValue.NewBoolean(rd.ReadBoolean());
|
|
|
+ case DataType.Number:
|
|
|
+ return DynValue.NewNumber(rd.ReadDouble());
|
|
|
+ case DataType.String:
|
|
|
+ return DynValue.NewString(rd.ReadString());
|
|
|
+ case DataType.Table :
|
|
|
+ return DynValue.NewTable(envTable);
|
|
|
+ default:
|
|
|
+ throw new NotSupportedException(string.Format("Unsupported type in chunk dump : {0}", dt));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ private void DumpValue(BinaryWriter wr, DynValue value)
|
|
|
+ {
|
|
|
+ if (value == null)
|
|
|
+ {
|
|
|
+ wr.Write(false);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ wr.Write(true);
|
|
|
+ wr.Write((byte)value.Type);
|
|
|
+
|
|
|
+ switch (value.Type)
|
|
|
+ {
|
|
|
+ case DataType.Nil:
|
|
|
+ case DataType.Void:
|
|
|
+ case DataType.Table:
|
|
|
+ break;
|
|
|
+ case DataType.Boolean:
|
|
|
+ wr.Write(value.Boolean);
|
|
|
+ break;
|
|
|
+ case DataType.Number:
|
|
|
+ wr.Write(value.Number);
|
|
|
+ break;
|
|
|
+ case DataType.String:
|
|
|
+ wr.Write(value.String);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ throw new NotSupportedException(string.Format("Unsupported type in chunk dump : {0}", value.Type));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ internal void GetSymbolReferences(out SymbolRef[] symbolList, out SymbolRef symbol)
|
|
|
+ {
|
|
|
+ int usage = (int)OpCode.GetFieldUsage();
|
|
|
+
|
|
|
+ symbol = null;
|
|
|
+ symbolList = null;
|
|
|
+
|
|
|
+ if ((usage & ((int)InstructionFieldUsage.Symbol)) != 0)
|
|
|
+ symbol = this.Symbol;
|
|
|
+
|
|
|
+ if ((usage & ((int)InstructionFieldUsage.SymbolList)) != 0)
|
|
|
+ symbolList = this.SymbolList;
|
|
|
+
|
|
|
+ }
|
|
|
}
|
|
|
}
|