using System; using System.Collections.Generic; using TLang.BytecodeCompiler; using TLang.Common; namespace TLang.VM { public class ChunkExecuter { public string ClassName {get;set;}=""; public ChunkExecuter(TVMFile file,Chunk chunk,TLangEnvironment env) { File =file; Chunk = chunk; Environment = env; } public TLangEnvironment Environment {get;set;} public TVMFile File {get;} public Chunk Chunk {get;} public int IP {get;set;}=0; public Stack Stack {get;}=new Stack(); public TObject Execute(params TObject[] args) { var env=Environment.GetSubEnvironment(); for(int i = 0;i< args.Length;i++) { if(i= File.Chunks.Count) throw new IndexOutOfRangeException($"No chunk with id {closureId}"); Stack.Push(new TClosure(File,File.Chunks[closureId],env)); break; case Instruction.PUSH_STRING: Stack.Push(new TString(ReadString())); break; case Instruction.PUSH_VARIABLE_VALUE: { var res=EnsurePop(); Stack.Push(env.GetObject(res.Value)); } break; case Instruction.POP_VARIABLE_VALUE: { var res=EnsurePop(); env.SetObject(res.Value,Stack.Pop()); } break; case Instruction.CALL_FUNC: { var argC = (int)EnsurePop().Value; TObject[] argV = new TObject[argC]; for(int i = argC;i>0;i--) { argV[i] = Stack.Pop(); } var name = EnsurePop(); var callable=env.GetObject(name.Value) as TCallable; if(callable != null) { Stack.Push(callable.Execute(argV)); }else{ Stack.Push(new TUndefined()); } } break; case Instruction.CALL_METHOD: { var argC = (int)EnsurePop().Value; TObject[] argV = new TObject[argC]; for(int i = argC;i>0;i--) { argV[i] = Stack.Pop(); } var name = EnsurePop(); var symbol = Stack.Pop(); Stack.Push(ExecuteMethod(symbol,name.Value,argV)); } break; } } if(Stack.Count > 0) return Stack.Pop(); return new TNull(); } private TObject ExecuteMethod(TObject symbol, string name, params TObject[] argV) { } private T EnsurePop() where T : TObject { var item = Stack.Pop() as T; if(item == null) throw new Exception("Pop failed"); return item; } private double ReadDouble() { if(IP + 8 < Chunk.Code.Length) { byte[] data =new byte[8]; Array.Copy(Chunk.Code,IP,data,0,8); IP += 8; if(BitConverter.IsLittleEndian) Array.Reverse(data); return BitConverter.ToDouble(data,0); } throw new Exception("Malformed binary"); } private int ReadInt() { if(IP + 4 < Chunk.Code.Length) { byte[] data =new byte[4]; Array.Copy(Chunk.Code,IP,data,0,4); IP += 4; if(BitConverter.IsLittleEndian) Array.Reverse(data); return BitConverter.ToInt32(data,0); } throw new Exception("Malformed binary"); } private string ReadString() { int strLen = ReadInt(); if(IP + strLen < Chunk.Code.Length) { var str=System.Text.Encoding.UTF8.GetString(Chunk.Code,IP,strLen); IP += strLen; return str; } throw new Exception("Malformed binary"); } private TObject Mod(TObject object1, TObject object2) { throw new NotImplementedException(); } private TObject Divide(TObject object1, TObject object2) { throw new NotImplementedException(); } private TObject Times(TObject object1, TObject object2) { throw new NotImplementedException(); } private TObject Sub(TObject object2, TObject object1) { throw new NotImplementedException(); } private TObject Add(TObject object2, TObject object1) { var left = object2 as TNumber; var right = object1 as TNumber; var lStr = object2 as TString; var rStr = object1 as TString; if(left != null && right != null) { return new TNumber(left.Value + right.Value); } if(lStr != null && rStr != null) { return new TString(lStr.Value + rStr.Value); } return new TNumber(0); } } }