1216 lines
41 KiB
C#
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);
|
|
}
|
|
}
|
|
|
|
|
|
}
|