CapersProject/Assets/Plugins/Pixel Crushers/Dialogue System/Scripts/Lua/Lua Interpreter/Expr/Operation.cs

343 lines
12 KiB
C#
Raw Normal View History

using System;
using System.Collections.Generic;
using System.Text;
namespace Language.Lua
{
/// <summary>
/// Represent Unary or Binary Operation, for Unary Operation the LeftOperand is not used.
/// </summary>
public partial class Operation : Term
{
public string Operator;
public Term LeftOperand;
public Term RightOperand;
public Operation(string oper)
{
this.Operator = oper;
}
public Operation(string oper, Term left, Term right)
{
this.Operator = oper;
this.LeftOperand = left == null ? null : left.Simplify();
this.RightOperand = right == null ? null : right.Simplify();
}
public override LuaValue Evaluate(LuaTable enviroment)
{
if (this.LeftOperand == null)
{
return PrefixUnaryOperation(Operator, RightOperand, enviroment);
}
else if (this.RightOperand == null)
{
return LeftOperand.Evaluate(enviroment);
}
else
{
return InfixBinaryOperation(LeftOperand, Operator, RightOperand, enviroment);
}
}
private LuaValue PrefixUnaryOperation(string Operator, Term RightOperand, LuaTable enviroment)
{
LuaValue rightValue = RightOperand.Evaluate(enviroment);
switch (Operator)
{
case "-":
var number = rightValue as LuaNumber;
if (number != null)
{
return new LuaNumber(-number.Number);
}
else
{
LuaFunction func = GetMetaFunction("__unm", rightValue, null);
if (func != null)
{
return func.Invoke(new LuaValue[] { rightValue });
}
}
break;
case "#":
var table = rightValue as LuaTable;
if (table != null)
{
return new LuaNumber(table.Length);
}
var str = rightValue as LuaString;
if (str != null)
{
return new LuaNumber(str.Text.Length);
}
break;
case "not":
var rightBool = rightValue as LuaBoolean;
if (rightBool != null)
{
return LuaBoolean.From(!rightBool.BoolValue);
}
break;
}
return LuaNil.Nil;
}
private LuaValue InfixBinaryOperation(Term LeftOperand, string Operator, Term RightOperand, LuaTable enviroment)
{
var isBooleanOperator = string.Equals(Operator, "and") || string.Equals(Operator, "or");
LuaValue leftValue = LeftOperand.Evaluate(enviroment);
LuaValue rightValue = isBooleanOperator ? null : RightOperand.Evaluate(enviroment); //[PixelCrushers] Short-circuit Boolean operators.
switch (Operator)
{
case "+":
var left = leftValue as LuaNumber;
var right = rightValue as LuaNumber;
if (left != null && right != null)
{
return new LuaNumber(left.Number + right.Number);
}
else
{
LuaFunction func = GetMetaFunction("__add", leftValue, rightValue);
if (func != null)
{
return func.Invoke(new LuaValue[] { leftValue, rightValue });
}
}
break;
case "-":
left = leftValue as LuaNumber;
right = rightValue as LuaNumber;
if (left != null && right != null)
{
return new LuaNumber(left.Number - right.Number);
}
else
{
LuaFunction func = GetMetaFunction("__sub", leftValue, rightValue);
if (func != null)
{
return func.Invoke(new LuaValue[] { leftValue, rightValue });
}
}
break;
case "*":
left = leftValue as LuaNumber;
right = rightValue as LuaNumber;
if (left != null && right != null)
{
return new LuaNumber(left.Number * right.Number);
}
else
{
LuaFunction func = GetMetaFunction("__mul", leftValue, rightValue);
if (func != null)
{
return func.Invoke(new LuaValue[] { leftValue, rightValue });
}
}
break;
case "/":
left = leftValue as LuaNumber;
right = rightValue as LuaNumber;
if (left != null && right != null)
{
return new LuaNumber(left.Number / right.Number);
}
else
{
LuaFunction func = GetMetaFunction("__div", leftValue, rightValue);
if (func != null)
{
return func.Invoke(new LuaValue[] { leftValue, rightValue });
}
}
break;
case "%":
left = leftValue as LuaNumber;
right = rightValue as LuaNumber;
if (left != null && right != null)
{
return new LuaNumber(left.Number % right.Number);
}
else
{
LuaFunction func = GetMetaFunction("__mod", leftValue, rightValue);
if (func != null)
{
return func.Invoke(new LuaValue[] { leftValue, rightValue });
}
}
break;
case "^":
left = leftValue as LuaNumber;
right = rightValue as LuaNumber;
if (left != null && right != null)
{
return new LuaNumber(Math.Pow(left.Number, right.Number));
}
else
{
LuaFunction func = GetMetaFunction("__pow", leftValue, rightValue);
if (func != null)
{
return func.Invoke(new LuaValue[] { leftValue, rightValue });
}
}
break;
case "==":
return LuaBoolean.From(leftValue.Equals(rightValue));
case "~=":
return LuaBoolean.From(leftValue.Equals(rightValue) == false);
case "<":
int? compare = Compare(leftValue, rightValue);
if (compare != null)
{
return LuaBoolean.From(compare < 0);
}
else
{
LuaFunction func = GetMetaFunction("__lt", leftValue, rightValue);
if (func != null)
{
return func.Invoke(new LuaValue[] { leftValue, rightValue });
}
}
break;
case ">":
compare = Compare(leftValue, rightValue);
if (compare != null)
{
return LuaBoolean.From(compare > 0);
}
else
{
LuaFunction func = GetMetaFunction("__gt", leftValue, rightValue);
if (func != null)
{
return func.Invoke(new LuaValue[] { leftValue, rightValue });
}
}
break;
case "<=":
compare = Compare(leftValue, rightValue);
if (compare != null)
{
return LuaBoolean.From(compare <= 0);
}
else
{
LuaFunction func = GetMetaFunction("__le", leftValue, rightValue);
if (func != null)
{
return func.Invoke(new LuaValue[] { leftValue, rightValue });
}
}
break;
case ">=":
compare = Compare(leftValue, rightValue);
if (compare != null)
{
return LuaBoolean.From(compare >= 0);
}
else
{
LuaFunction func = GetMetaFunction("__ge", leftValue, rightValue);
if (func != null)
{
return func.Invoke(new LuaValue[] { leftValue, rightValue });
}
}
break;
case "..":
if ((leftValue is LuaString || leftValue is LuaNumber) &&
(rightValue is LuaString || rightValue is LuaNumber))
{
return new LuaString(string.Concat(leftValue, rightValue));
}
else
{
LuaFunction func = GetMetaFunction("__concat", leftValue, rightValue);
if (func != null)
{
return func.Invoke(new LuaValue[] { leftValue, rightValue });
}
}
break;
case "and":
bool leftBool = leftValue.GetBooleanValue();
if (leftBool == false)
{
return leftValue;
}
else
{
return RightOperand.Evaluate(enviroment);
}
case "or":
leftBool = leftValue.GetBooleanValue();
if (leftBool == true)
{
return leftValue;
}
else
{
return RightOperand.Evaluate(enviroment);
}
}
return null;
}
private static int? Compare(LuaValue leftValue, LuaValue rightValue)
{
LuaNumber left = leftValue as LuaNumber;
LuaNumber right = rightValue as LuaNumber;
if (left != null && right != null)
{
return left.Number.CompareTo(right.Number);
}
LuaString leftString = leftValue as LuaString;
LuaString rightString = rightValue as LuaString;
if (leftString != null && rightString != null)
{
return StringComparer.Ordinal.Compare(leftString.Text, rightString.Text);
}
return null;
}
private static LuaFunction GetMetaFunction(string name, LuaValue leftValue, LuaValue rightValue)
{
LuaTable left = leftValue as LuaTable;
if (left != null)
{
LuaFunction func = left.GetValue(name) as LuaFunction;
if (func != null)
{
return func;
}
}
LuaTable right = rightValue as LuaTable;
if (right != null)
{
return right.GetValue(name) as LuaFunction;
}
return null;
}
}
}