tlang-runtime-compiler/TLang.VM/TClassInstance.cs

168 lines
6.7 KiB
C#

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<string> InheritenceTree {get;}=new List<string>();
public Dictionary<string,ClassMethod> Methods {get;} = new Dictionary<string, ClassMethod>();
public Dictionary<string,ClassField> Fields {get;} = new Dictionary<string, ClassField>();
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();
}
}
}