using System; using System.Collections.Generic; namespace TLang.VM { public class TClassInstance : TObject { public override string Type => $"class {classEntry.Name} : {classEntry.InheritsFrom}"; public override bool True => true; TVMFile file; Class classEntry; TLangEnvironment oGenv; public TClassInstance(TVMFile file,Class classEntry,TLangEnvironment env) { this.file = file; this.classEntry = classEntry; this.oGenv = env; } public List InheritenceTree {get;}=new List(); public Dictionary Methods {get;} = new Dictionary(); public Dictionary Fields {get;} = new Dictionary(); public void Init(params TObject[] args) { Environment = new ClassEnvironment(oGenv,this); foreach(var item in classEntry.ClassEntries) { if(item.Method) { ClassMethod meth=new ClassMethod(); TClosure closure=new TClosure(file,file.Chunks[item.ChunkId],Environment); meth.Private = item.Private; meth.Protected = item.Protected; meth.Closure = closure; meth.ClassName = classEntry.Name; Methods.Add(item.Name,meth); } else { ClassField field = new ClassField(); field.ClassName = classEntry.Name; TClosure closure = new TClosure(file,file.Chunks[item.ChunkId],Environment); field.Private = item.Private; field.Protected = item.Protected; field.Value = closure.Execute(); Fields.Add(item.Name,field); } } var cE = classEntry; var aC =oGenv.GetRootEnvironment().AvailableClasses; //we need to check inheritence while(cE.InheritsFrom != "object" && cE.InheritsFrom != "") { InheritenceTree.Add(cE.InheritsFrom); if(aC.ContainsKey(cE.InheritsFrom)) { var aC2 = aC[cE.InheritsFrom]; cE = aC2.ToClass(cE.InheritsFrom); foreach(var item in cE.ClassEntries) { if(!Fields.ContainsKey(item.Name) && !item.Method) { ClassField field = new ClassField(); field.ClassName = cE.Name; TClosure closure = new TClosure(aC2.File,aC2.File.Chunks[item.ChunkId],Environment); field.Private = item.Private; field.Protected = item.Protected; field.Value = closure.Execute(); Fields.Add(item.Name,field); } if(!Methods.ContainsKey(item.Name) && item.Method) { if(item.Abstract) throw new Exception("Method is abstract"); ClassMethod meth=new ClassMethod(); TClosure closure=new TClosure(aC2.File,aC2.File.Chunks[item.ChunkId],Environment); meth.ClassName = cE.Name; meth.Closure = closure; meth.Private = item.Private; meth.Protected = item.Protected; Methods.Add(item.Name,meth); } } } } if(!Methods.ContainsKey("toString")) { Methods.Add("toString",new ClassMethod(){ClassName="object", Closure = new TExternalMethod(e=>new TString($"class {classEntry.Name} : {classEntry.InheritsFrom}")), Private=false, Protected = false}); } if(Methods.ContainsKey(classEntry.Name)) { var ctor=Methods[classEntry.Name]; if(ctor.ClassName == classEntry.Name) { ctor.Closure.ClassName = classEntry.Name; ctor.Closure.Execute(args); } } } public TLangEnvironment Environment {get; private set;} public void SetField(string className,string key,TObject obj) { if(Fields.ContainsKey(key)) { var field=Fields[key]; if(field.Private && className != classEntry.Name) return; if(field.Protected && className != classEntry.Name && !InheritenceTree.Contains(className)) return; field.Value=obj; } } public TObject GetField(string className,string key) { if(Fields.ContainsKey(key)) { var field=Fields[key]; if(field.Private && className != classEntry.Name) return new TUndefined(); if(field.Protected && className != classEntry.Name && !InheritenceTree.Contains(className)) return new TUndefined(); return field.Value; } return new TUndefined(); } public bool MethodExists(string className,string key) { if(Methods.ContainsKey(key)) { var method=Methods[key]; if(method.Private && className != classEntry.Name) return false; if(method.Protected && className != classEntry.Name && !InheritenceTree.Contains(className)) return false; return true; } return false; } public TObject CallMethod(string className,string key,params TObject[] args) { if(Methods.ContainsKey(key)) { var method=Methods[key]; if(method.Private && className != classEntry.Name) return new TUndefined(); if(method.Protected && className != classEntry.Name && !InheritenceTree.Contains(className)) return new TUndefined(); method.Closure.ClassName = method.ClassName; return method.Closure.Execute(args); } return new TUndefined(); } public override string ToString() { return CallMethod(classEntry.Name,"toString").ToString(); } } }