using System; using System.Collections.Generic; using System.IO; using TLang.Common; namespace TLang.VM { public class TVMFile { public List Classes {get;set;}=new List(); public List Functions {get;set;}=new List(); public List Dependencies {get;set;}=new List(); public List Chunks {get;set;}=new List(); public TLangVersion Version {get;set;} public RootEnvironment Environment {get;private set;} public ChunkExecuter DefaultChunkExecuter => new ChunkExecuter(this,Chunks[0],Environment); public TVMFile(Stream file,RootEnvironment env) { Environment = env; byte[] data=new byte[11]; int read=file.Read(data,0,data.Length); CheckData(data,read); int deps=ReadBigEndianIntenger(file); for(int i = 0;i 0) read0=file.Read(code,offset,read0); offset+=read0; } while(read0 > 0); chunk.Code = code; Chunks.Add(chunk); } } private void EnsureRead(Stream file,byte[] data) { int i = file.Read(data,0,data.Length); if(i != data.Length) throw new IndexOutOfRangeException("Array must be filled"); } private int ReadBigEndianIntenger(Stream file) { byte[] bytes=new byte[4]; EnsureRead(file,bytes); if(BitConverter.IsLittleEndian) Array.Reverse(bytes); return BitConverter.ToInt32(bytes,0); } private void CheckData(byte[] data, int read) { if(read < 11 || data[0] != 'T' || data[1] != 'V' || data[2] != 'M') throw new BadImageFormatException("TVM file invalid"); if(TLangVersion.FromBytes(data,3).IntegerVersion > TLangVersion.Version.IntegerVersion) throw new BadImageFormatException("TVM Version is too old"); Version = TLangVersion.FromBytes(data,7); } public bool LoadDependencies(IDependencyPool dependencyPool) { foreach(var dep in Dependencies) { if(!dependencyPool.DependencyExists(dep)) { if(!dependencyPool.AddDependency(dep,Environment)) return false; } } foreach(var func in Functions) { Environment.SetObject(func.Name,new TClosure(this,Chunks[func.ChunkId],Environment)); } foreach(var class0 in Classes) { Environment.AvailableClasses.Add(class0.Name,new LoadedClassData(class0.InheritsFrom,this,class0.ClassEntries)); Environment.SetObject(class0.Name,new TExternalMethod(args=>{ TClassInstance instance = new TClassInstance(this,class0,Environment); instance.Init(args); return instance; })); } return true; } } }