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

1216 lines
41 KiB
C#

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.GetSubEnvironment();
}
public TLangEnvironment Environment {get;set;}
public TVMFile File {get;}
public Chunk Chunk {get;}
public int IP {get;set;}=0;
public Stack<TObject> Stack {get;}=new Stack<TObject>();
public TObject Execute(params TObject[] args)
{
for(int i = 0;i< args.Length;i++)
{
if(i<Chunk.Arguments.Count)
{
Environment.SetObject(Chunk.Arguments[i],args[i]);
}
}
while(IP < Chunk.Code.Length)
{
var instruction = Chunk.Code[IP++];
switch(instruction)
{
case Instruction.ADD:
Stack.Push(Add(Stack.Pop(),Stack.Pop()));
break;
case Instruction.SUB:
Stack.Push(Sub(Stack.Pop(),Stack.Pop()));
break;
case Instruction.TIMES:
Stack.Push(Times(Stack.Pop(),Stack.Pop()));
break;
case Instruction.DIVIDE:
Stack.Push(Divide(Stack.Pop(),Stack.Pop()));
break;
case Instruction.MOD:
Stack.Push(Mod(Stack.Pop(),Stack.Pop()));
break;
case Instruction.POW:
Stack.Push(Pow(Stack.Pop(),Stack.Pop()));
break;
case Instruction.LT:
Stack.Push(LT(Stack.Pop(),Stack.Pop()));
break;
case Instruction.LTE:
Stack.Push(LTE(Stack.Pop(),Stack.Pop()));
break;
case Instruction.GT:
Stack.Push(GT(Stack.Pop(),Stack.Pop()));
break;
case Instruction.GTE:
Stack.Push(GTE(Stack.Pop(),Stack.Pop()));
break;
case Instruction.LAND:
Stack.Push(LAnd(Stack.Pop(),Stack.Pop()));
break;
case Instruction.LOR:
Stack.Push(LOr(Stack.Pop(),Stack.Pop()));
break;
case Instruction.XOR:
Stack.Push(XOr(Stack.Pop(),Stack.Pop()));
break;
case Instruction.LSHIFT:
Stack.Push(LShift(Stack.Pop(),Stack.Pop()));
break;
case Instruction.RSHIFT:
Stack.Push(RShift(Stack.Pop(),Stack.Pop()));
break;
case Instruction.BAND:
Stack.Push(BAnd(Stack.Pop(),Stack.Pop()));
break;
case Instruction.BNOT:
Stack.Push(BNot(Stack.Pop()));
break;
case Instruction.BOR:
Stack.Push(BOr(Stack.Pop(),Stack.Pop()));
break;
case Instruction.EQ:
Stack.Push(Eq(Stack.Pop(),Stack.Pop()));
break;
case Instruction.NEQ:
Stack.Push(NEq(Stack.Pop(),Stack.Pop()));
break;
case Instruction.NEG:
Stack.Push(Negative(Stack.Pop()));
break;
case Instruction.RET:
return Stack.Pop();
case Instruction.SCOPE_BEGIN:
Environment = Environment.GetSubEnvironment();
break;
case Instruction.SCOPE_END:
Environment = Environment.GetParentEnvironment();
break;
case Instruction.PUSH_DOUBLE:
Stack.Push(new TNumber(ReadDouble()));
break;
case Instruction.PUSH_CLOSURE:
int closureId = ReadInt();
if(closureId >= File.Chunks.Count) throw new IndexOutOfRangeException($"No chunk with id {closureId}");
Stack.Push(new TClosure(File,File.Chunks[closureId],Environment){ClassName = ClassName});
break;
case Instruction.PUSH_STRING:
Stack.Push(new TString(ReadString()));
break;
case Instruction.PUSH_VARIABLE_VALUE:
{
var res=EnsurePop<TString>();
Stack.Push(Environment.GetObject(res.Value));
}
break;
case Instruction.PUSH_FIELD_VALUE:
{
var res= EnsurePop<TString>();
var symbol = Stack.Pop();
Stack.Push(GetFieldValue(symbol,res.Value));
}
break;
case Instruction.POP_FIELD_VALUE:
{
var val = Stack.Pop();
var res= EnsurePop<TString>();
var symbol = Stack.Pop();
SetFieldValue(symbol, res.Value, val);
}
break;
case Instruction.POP_VARIABLE_VALUE:
{
var val = Stack.Pop();
var res=EnsurePop<TString>();
Environment.SetObject(res.Value,val);
}
break;
case Instruction.NOP:
break;
case Instruction.PUSH_CHAR:
Stack.Push(new TChar((char)Chunk.Code[IP++]));
break;
case Instruction.PUSH_ARRAY_VALUE:
{
var expr = Stack.Pop();
var symbol = Stack.Pop();
Stack.Push(GetArrayValue(symbol,expr));
}
break;
case Instruction.POP_ARRAY_VALUE:
{
var val = Stack.Pop();
var expr = Stack.Pop();
var symbol = Stack.Pop();
SetArrayValue(symbol,expr,val);
}
break;
case Instruction.PUSH_UNDEFINED:
Stack.Push(new TUndefined());
break;
case Instruction.PUSH_NULL:
Stack.Push(new TNull());
break;
case Instruction.PUSH_TRUE:
Stack.Push(new TBool(true));
break;
case Instruction.PUSH_FALSE:
Stack.Push(new TBool(false));
break;
case Instruction.CALL_FUNC:
{
var argC = (int)EnsurePop<TNumber>().Value;
TObject[] argV = new TObject[argC];
for(int i = argC;i>0;i--)
{
argV[i-1] = Stack.Pop();
}
var name = EnsurePop<TString>();
var callable=Environment.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<TNumber>().Value;
TObject[] argV = new TObject[argC];
for(int i = argC;i>0;i--)
{
argV[i-1] = Stack.Pop();
}
var name = EnsurePop<TString>();
var symbol = Stack.Pop();
Stack.Push(ExecuteMethod(symbol,name.Value,argV));
}
break;
case Instruction.JMP:
IP=ReadInt();
break;
case Instruction.JMPC:
{
int jmpPos = ReadInt();
if(Stack.Pop().True)
IP = jmpPos;
}
break;
case Instruction.LNOT:
{
var res=Stack.Pop();
Stack.Push(LNot(res));
}
break;
case Instruction.POP:
Stack.Pop();
break;
}
}
if(Stack.Count > 0)
return Stack.Pop();
return new TNull();
}
private TObject SetArrayValue(TObject symbol,TObject expr,TObject value)
{
var classMethod = symbol as TClassInstance;
var dict = symbol as TDictionary;
var array = symbol as TArray;
if(array != null)
{
var index = expr as TNumber;
if(index != null && ((int)index.Value) < array.Items.Count)
{
array.Items[(int)index.Value] = value;
return new TUndefined();
}
}
if(classMethod != null)
{
if(classMethod.MethodExists(ClassName,"iset"))
{
return classMethod.CallMethod(ClassName,"iset",expr,value);
}
var index = expr as TString;
if(index != null)
{
classMethod.SetField(ClassName,index.Value,value);
return new TUndefined();
}
}
if(dict != null)
{
if(dict.HasValue("iset"))
{
var iget = dict.GetValue("iset") as TCallable;
if(iget != null)
{
return iget.Execute(expr,value);
}
var index = expr as TString;
if(index != null)
dict.SetValue(index.Value,value);
}
}
return new TUndefined();
}
private TObject GetArrayValue(TObject symbol, TObject expr)
{
var classMethod = symbol as TClassInstance;
var dict = symbol as TDictionary;
var str = symbol as TString;
var array = symbol as TArray;
if(str != null)
{
var index = expr as TNumber;
if(index != null && ((int)index.Value) < str.Value.Length)
{
return new TChar(str.Value[(int)index.Value]);
}
}
if(array != null)
{
var index = expr as TNumber;
if(index != null && ((int)index.Value) < array.Items.Count)
{
return array.Items[(int)index.Value];
}
}
if(classMethod != null)
{
if(classMethod.MethodExists(ClassName,"iget"))
{
return classMethod.CallMethod(ClassName,"iget",expr);
}
var index = expr as TString;
if(index != null)
{
return classMethod.GetField(ClassName,index.Value);
}
}
if(dict != null)
{
if(dict.HasValue("iget"))
{
var iget = dict.GetValue("iget") as TCallable;
if(iget != null)
{
return iget.Execute(expr);
}
var index = expr as TString;
if(index != null)
return dict.GetValue(index.Value);
}
}
return new TUndefined();
}
private TObject LNot(TObject res)
{
var classMethod = res as TClassInstance;
var dict = res as TDictionary;
if(classMethod != null)
{
return classMethod.CallMethod(ClassName,"lnot",res);
}
if(dict != null)
{
var callable= dict.GetValue("lnot") as TCallable;
if(callable != null)
{
return callable.Execute(res);
}
}
return new TBool(!res.True);
}
private TObject Negative(TObject object1)
{
var left = object1 as TNumber;
var lcls = object1 as TClassInstance;
var ldict = object1 as TDictionary;
if(left != null)
{
return new TNumber(-(left.Value));
}
if(lcls != null && lcls.MethodExists(ClassName,"neg"))
{
return lcls.CallMethod(ClassName,"neg");
}
if(ldict != null)
{
var callable =ldict.GetValue("neg") as TCallable;
if(callable != null) return callable.Execute();
}
return new TNumber(0);
}
private TObject BNot(TObject object1)
{
var left = object1 as TNumber;
var lcls = object1 as TClassInstance;
var ldict = object1 as TDictionary;
if(left != null)
{
return new TNumber(~((long)left.Value));
}
if(lcls != null && lcls.MethodExists(ClassName,"band"))
{
return lcls.CallMethod(ClassName,"bnot");
}
if(ldict != null)
{
var callable =ldict.GetValue("bnot") as TCallable;
if(callable != null) return callable.Execute();
}
return new TNumber(0);
}
private TObject GetFieldValue(TObject symbol, string name)
{
var classField = symbol as TClassInstance;
var dict = symbol as TDictionary;
var tArray = symbol as TArray;
var tString = symbol as TString;
if(tArray != null)
{
if(name == "count")
{
return new TNumber(tArray.Items.Count);
}
if(name == "empty")
{
return new TBool(!tArray.True);
}
if(name == "ittr")
{
return TDictionary.FromIEnumerator(tArray.Items.GetEnumerator());
}
}
if(tString != null)
{
if(name == "count")
{
return new TNumber(tString.Value.Length);
}
if(name == "empty")
{
return new TBool(tString.Value.Length == 0);
}
if(name == "ittr")
{
return TDictionary.FromIEnumerator(tString.GetObjects().GetEnumerator());
}
}
if(classField != null)
{
if(classField.MethodExists(ClassName,$"get{name}"))
{
return classField.CallMethod(ClassName,$"get{name}");
}
return classField.GetField(ClassName,name);
}
if(dict != null)
{
var callable= dict.GetValue($"get{name}") as TCallable;
if(callable != null)
{
return callable.Execute();
}
else
{
return dict.GetValue(name);
}
}
return new TUndefined();
}
public void SetFieldValue(TObject symbol, string name,TObject newValue)
{
var classField = symbol as TClassInstance;
var dict = symbol as TDictionary;
if(classField != null)
{
if(classField.MethodExists(ClassName,$"set{name}"))
{
classField.CallMethod(ClassName,$"set{name}",newValue);
}
else
{
classField.SetField(ClassName,name,newValue);
}
}
if(dict != null)
{
var callable= dict.GetValue($"set{name}") as TCallable;
if(callable != null)
{
callable.Execute(newValue);
}
else
{
dict.SetValue(name,newValue);
}
}
}
private TObject ExecuteMethod(TObject symbol, string name, params TObject[] argV)
{
if(name == "toString" && argV.Length == 0) return new TString(symbol.ToString());
var classMethod = symbol as TClassInstance;
var number = symbol as TNumber;
var dict = symbol as TDictionary;
var tArray = symbol as TArray;
var tString = symbol as TString;
if(tString != null)
{
if(name == "count")
{
return new TNumber(tString.Value.Length);
}
if(name == "empty")
{
return new TBool(tString.Value.Length == 0);
}
var strP=Environment.GetObject("String") as TDictionary;
if(strP != null)
{
var func = strP.GetValue(name) as TCallable;
if(func != null)
{
List<TObject> arguments = new List<TObject>();
arguments.Add(symbol);
arguments.AddRange(argV);
return func.Execute(arguments.ToArray());
}
}
}
if(classMethod != null)
{
return classMethod.CallMethod(ClassName,name,argV);
}
if(dict != null)
{
var callable= dict.GetValue(name) as TCallable;
if(callable != null)
{
return callable.Execute(argV);
}
}
if(tArray != null)
{
if(name == "add")
{
if(argV.Length > 0)
{
tArray.Add(argV[0]);
}
return tArray;
}
if(name == "remove")
{
if(argV.Length > 0)
{
tArray.Remove(argV[0]);
}
return tArray;
}
if(name == "removeat")
{
if(argV.Length > 0)
{
var num = argV[0] as TNumber;
if(num != null)
{
tArray.Items.RemoveAt((int)num.Value);
}
}
return tArray;
}
if(name == "clear")
{
tArray.Items.Clear();
return tArray;
}
if(name == "count")
{
return new TNumber(tArray.Items.Count);
}
if(name == "empty")
{
return new TBool(!tArray.True);
}
var strP=Environment.GetObject("Array") as TDictionary;
if(strP != null)
{
var func = strP.GetValue(name) as TCallable;
if(func != null)
{
List<TObject> arguments = new List<TObject>();
arguments.Add(symbol);
arguments.AddRange(argV);
return func.Execute(arguments.ToArray());
}
}
}
if(number != null)
{
if(name == "floor")
{
return new TNumber(Math.Floor(number.Value));
}
if(name == "ceil")
{
return new TNumber(Math.Ceiling(number.Value));
}
if(name == "round")
{
if(argV.Length > 0)
{
var n = argV[0] as TNumber;
if(n !=null)
return new TNumber(Math.Round(number.Value,(int)n.Value));
}
return new TNumber(Math.Round(number.Value));
}
if(name == "toChar")
{
return new TChar((char)(int)number.Value);
}
var strP=Environment.GetObject("Number") as TDictionary;
if(strP != null)
{
var func = strP.GetValue(name) as TCallable;
if(func != null)
{
List<TObject> arguments = new List<TObject>();
arguments.Add(symbol);
arguments.AddRange(argV);
return func.Execute(arguments.ToArray());
}
}
return new TNull();
}
return new TUndefined();
}
private T EnsurePop<T>() 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 BAnd(TObject object2, TObject object1)
{
var left = object1 as TNumber;
var right = object2 as TNumber;
var lcls = object1 as TClassInstance;
var ldict = object1 as TDictionary;
if(left != null && right != null)
{
return new TNumber((long)left.Value & (long)right.Value);
}
if(lcls != null && lcls.MethodExists(ClassName,"band"))
{
return lcls.CallMethod(ClassName,"band",object2);
}
if(ldict != null)
{
var callable =ldict.GetValue("band") as TCallable;
if(callable != null) return callable.Execute(object2);
}
return new TNumber(0);
}
private TObject BOr(TObject object2, TObject object1)
{
var left = object1 as TNumber;
var right = object2 as TNumber;
var lcls = object1 as TClassInstance;
var ldict = object1 as TDictionary;
if(left != null && right != null)
{
return new TNumber((long)left.Value | (long)right.Value);
}
if(lcls != null && lcls.MethodExists(ClassName,"bor"))
{
return lcls.CallMethod(ClassName,"bor",object2);
}
if(ldict != null)
{
var callable =ldict.GetValue("bor") as TCallable;
if(callable != null) return callable.Execute(object2);
}
return new TNumber(0);
}
private TObject NEq(TObject object2, TObject object1)
{
var left = object1 as TNumber;
var right = object2 as TNumber;
var lStr = object1 as TString;
var rStr = object2 as TString;
var lChr = object1 as TChar;
var rChr = object2 as TChar;
var lBool = object1 as TBool;
var rBool = object2 as TBool;
var lcls = object1 as TClassInstance;
var ldict = object1 as TDictionary;
if(left != null && right != null)
{
return new TBool(left.Value != right.Value);
}
if(lStr != null && rStr != null)
{
return new TBool(lStr.Value != lStr.Value);
}
if(lChr != null && rChr != null)
{
return new TBool(lChr.Value != lChr.Value);
}
if(lBool != null && rBool != null)
{
return new TBool(lBool.Value != lBool.Value);
}
if(lcls != null && lcls.MethodExists(ClassName,"neq"))
{
return lcls.CallMethod(ClassName,"neq",object2);
}
if(ldict != null)
{
var callable =ldict.GetValue("neq") as TCallable;
if(callable != null) return callable.Execute(object2);
}
return new TBool(object1 != object2);
}
private TObject Eq(TObject object2, TObject object1)
{
var left = object1 as TNumber;
var right = object2 as TNumber;
var lStr = object1 as TString;
var rStr = object2 as TString;
var lChr = object1 as TChar;
var rChr = object2 as TChar;
var lBool = object1 as TBool;
var rBool = object2 as TBool;
var lcls = object1 as TClassInstance;
var ldict = object1 as TDictionary;
if(left != null && right != null)
{
return new TBool(left.Value == right.Value);
}
if(lStr != null && rStr != null)
{
return new TBool(lStr.Value == lStr.Value);
}
if(lChr != null && rChr != null)
{
return new TBool(lChr.Value == lChr.Value);
}
if(lBool != null && rBool != null)
{
return new TBool(lBool.Value == lBool.Value);
}
if(lcls != null && lcls.MethodExists(ClassName,"eq"))
{
return lcls.CallMethod(ClassName,"eq",object2);
}
if(ldict != null)
{
var callable =ldict.GetValue("eq") as TCallable;
if(callable != null) return callable.Execute(object2);
}
return new TBool(object1 == object2);
}
private TObject RShift(TObject object2, TObject object1)
{
var left = object1 as TNumber;
var right = object2 as TNumber;
var lcls = object1 as TClassInstance;
var ldict = object1 as TDictionary;
if(left != null && right != null)
{
return new TNumber((long)left.Value >> (int)right.Value);
}
if(lcls != null && lcls.MethodExists(ClassName,"rs"))
{
return lcls.CallMethod(ClassName,"rs",object2);
}
if(ldict != null)
{
var callable =ldict.GetValue("rs") as TCallable;
if(callable != null) return callable.Execute(object2);
}
return new TNumber(0);
}
private TObject LShift(TObject object2, TObject object1)
{
var left = object1 as TNumber;
var right = object2 as TNumber;
var lcls = object1 as TClassInstance;
var ldict = object1 as TDictionary;
if(left != null && right != null)
{
return new TNumber((long)left.Value << (int)right.Value);
}
if(lcls != null && lcls.MethodExists(ClassName,"ls"))
{
return lcls.CallMethod(ClassName,"ls",object2);
}
if(ldict != null)
{
var callable =ldict.GetValue("ls") as TCallable;
if(callable != null) return callable.Execute(object2);
}
return new TNumber(0);
}
private TObject XOr(TObject object2, TObject object1)
{
var lcls = object1 as TClassInstance;
var ldict = object1 as TDictionary;
if(lcls != null && lcls.MethodExists(ClassName,"lte"))
{
return lcls.CallMethod(ClassName,"lte",object2);
}
if(ldict != null)
{
var callable =ldict.GetValue("lte") as TCallable;
if(callable != null) return callable.Execute(object2);
}
return new TBool(object1.True ^ object2.True);
}
private TObject LOr(TObject object2, TObject object1)
{
var lcls = object1 as TClassInstance;
var ldict = object1 as TDictionary;
if(lcls != null && lcls.MethodExists(ClassName,"lor"))
{
return lcls.CallMethod(ClassName,"lor",object2);
}
if(ldict != null)
{
var callable =ldict.GetValue("lor") as TCallable;
if(callable != null) return callable.Execute(object2);
}
return new TBool(object1.True || object2.True);
}
private TObject LAnd(TObject object2, TObject object1)
{
var lcls = object1 as TClassInstance;
var ldict = object1 as TDictionary;
if(lcls != null && lcls.MethodExists(ClassName,"land"))
{
return lcls.CallMethod(ClassName,"land",object2);
}
if(ldict != null)
{
var callable =ldict.GetValue("land") as TCallable;
if(callable != null) return callable.Execute(object2);
}
return new TBool(object1.True && object2.True);
}
private TObject Pow(TObject object1, TObject object2)
{
var left = object1 as TNumber;
var right = object2 as TNumber;
var lcls = object1 as TClassInstance;
var ldict = object1 as TDictionary;
if(left != null && right != null)
{
return new TNumber(Math.Pow(left.Value,right.Value));
}
if(lcls != null && lcls.MethodExists(ClassName,"pow"))
{
return lcls.CallMethod(ClassName,"pow",object2);
}
if(ldict != null)
{
var callable =ldict.GetValue("pow") as TCallable;
if(callable != null) return callable.Execute(object2);
}
return new TNumber(0);
}
private TObject Mod(TObject object1, TObject object2)
{
var left = object1 as TNumber;
var right = object2 as TNumber;
var lcls = object1 as TClassInstance;
var ldict = object1 as TDictionary;
if(left != null && right != null)
{
return new TNumber(left.Value % right.Value);
}
if(lcls != null && lcls.MethodExists(ClassName,"mod"))
{
return lcls.CallMethod(ClassName,"mod",object2);
}
if(ldict != null)
{
var callable =ldict.GetValue("mod") as TCallable;
if(callable != null) return callable.Execute(object2);
}
return new TNumber(0);
}
private TObject Divide(TObject object1, TObject object2)
{
var left = object1 as TNumber;
var right = object2 as TNumber;
var lcls = object1 as TClassInstance;
var ldict = object1 as TDictionary;
if(left != null && right != null)
{
return new TNumber(left.Value / right.Value);
}
if(lcls != null && lcls.MethodExists(ClassName,"div"))
{
return lcls.CallMethod(ClassName,"div",object2);
}
if(ldict != null)
{
var callable =ldict.GetValue("div") as TCallable;
if(callable != null) return callable.Execute(object2);
}
return new TNumber(0);
}
private TObject Times(TObject object1, TObject object2)
{
var left = object1 as TNumber;
var right = object2 as TNumber;
var lcls = object1 as TClassInstance;
var ldict = object1 as TDictionary;
if(left != null && right != null)
{
return new TNumber(left.Value + right.Value);
}
if(lcls != null && lcls.MethodExists(ClassName,"times"))
{
return lcls.CallMethod(ClassName,"times",object2);
}
if(ldict != null)
{
var callable =ldict.GetValue("times") as TCallable;
if(callable != null) return callable.Execute(object2);
}
return new TNumber(0);
}
private TObject Sub(TObject object2, TObject object1)
{
var left = object1 as TNumber;
var right = object2 as TNumber;
var lStr = object1 as TString;
var rStr = object2 as TString;
var lcls = object1 as TClassInstance;
var ldict = object1 as TDictionary;
var lArray = object1 as TArray;
if(left != null && right != null)
{
return new TNumber(left.Value - right.Value);
}
if(lcls != null && lcls.MethodExists(ClassName,"sub"))
{
return lcls.CallMethod(ClassName,"sub",object2);
}
if(ldict != null)
{
var callable =ldict.GetValue("sub") as TCallable;
if(callable != null) return callable.Execute(object2);
}
if(lArray != null)
{
lArray.Remove(object2);
return lArray;
}
return new TNumber(0);
}
private TObject GTE(TObject object2, TObject object1)
{
var left = object1 as TNumber;
var right = object2 as TNumber;
var lStr = object1 as TString;
var rStr = object2 as TString;
var lcls = object1 as TClassInstance;
var ldict = object1 as TDictionary;
if(left != null && right != null)
{
return new TBool(left.Value >= right.Value);
}
if(lcls != null && lcls.MethodExists(ClassName,"gte"))
{
return lcls.CallMethod(ClassName,"gte",object2);
}
if(ldict != null)
{
var callable =ldict.GetValue("gte") as TCallable;
if(callable != null) return callable.Execute(object2);
}
return new TNumber(0);
}
private TObject GT(TObject object2, TObject object1)
{
var left = object1 as TNumber;
var right = object2 as TNumber;
var lStr = object1 as TString;
var rStr = object2 as TString;
var lcls = object1 as TClassInstance;
var ldict = object1 as TDictionary;
if(left != null && right != null)
{
return new TBool(left.Value > right.Value);
}
if(lcls != null && lcls.MethodExists(ClassName,"gt"))
{
return lcls.CallMethod(ClassName,"gt",object2);
}
if(ldict != null)
{
var callable =ldict.GetValue("gt") as TCallable;
if(callable != null) return callable.Execute(object2);
}
return new TNumber(0);
}
private TObject LTE(TObject object2, TObject object1)
{
var left = object1 as TNumber;
var right = object2 as TNumber;
var lStr = object1 as TString;
var rStr = object2 as TString;
var lcls = object1 as TClassInstance;
var ldict = object1 as TDictionary;
if(left != null && right != null)
{
return new TBool(left.Value <= right.Value);
}
if(lcls != null && lcls.MethodExists(ClassName,"lte"))
{
return lcls.CallMethod(ClassName,"lte",object2);
}
if(ldict != null)
{
var callable =ldict.GetValue("lte") as TCallable;
if(callable != null) return callable.Execute(object2);
}
return new TNumber(0);
}
private TObject LT(TObject object2, TObject object1)
{
var left = object1 as TNumber;
var right = object2 as TNumber;
var lStr = object1 as TString;
var rStr = object2 as TString;
var lcls = object1 as TClassInstance;
var ldict = object1 as TDictionary;
if(left != null && right != null)
{
return new TBool(left.Value < right.Value);
}
if(lcls != null && lcls.MethodExists(ClassName,"lt"))
{
return lcls.CallMethod(ClassName,"lt",object2);
}
if(ldict != null)
{
var callable =ldict.GetValue("lt") as TCallable;
if(callable != null) return callable.Execute(object2);
}
return new TNumber(0);
}
private TObject Add(TObject object2, TObject object1)
{
var left = object1 as TNumber;
var right = object2 as TNumber;
var lStr = object1 as TString;
var rStr = object2 as TString;
var lcls = object1 as TClassInstance;
var ldict = object1 as TDictionary;
var lArray = object1 as TArray;
if(left != null && right != null)
{
return new TNumber(left.Value + right.Value);
}
if(lStr != null && rStr != null)
{
return new TString(lStr.Value + rStr.Value);
}
if(lcls != null && lcls.MethodExists(ClassName,"add"))
{
return lcls.CallMethod(ClassName,"add",object2);
}
if(ldict != null)
{
var callable =ldict.GetValue("add") as TCallable;
if(callable != null) return callable.Execute(object2);
}
if(lArray != null)
{
lArray.Add(object2);
return lArray;
}
return new TNumber(0);
}
}
}