Handle Unary operator overloading for UserData

This commit is contained in:
Deukhoofd 2018-11-21 13:54:41 +01:00
parent c627100e9c
commit 605b98284d
No known key found for this signature in database
GPG Key ID: B4C087AC81641654
5 changed files with 59 additions and 2 deletions

View File

@ -48,5 +48,10 @@ namespace Upsilon.BaseTypes.UserData
{ {
return _typeInfo.BinaryOperator(Value, par1, op, par2); return _typeInfo.BinaryOperator(Value, par1, op, par2);
} }
public (LuaType Type, bool Failed) UnaryOperator(LuaType par1, OperatorType op)
{
return _typeInfo.UnaryOperator(Value, par1, op);
}
} }
} }

View File

@ -82,5 +82,15 @@ namespace Upsilon.BaseTypes.UserData
return (method.Invoke(value, new[] {par1.ToCSharpObject(), par2.ToCSharpObject()}).ToLuaType(), false); return (method.Invoke(value, new[] {par1.ToCSharpObject(), par2.ToCSharpObject()}).ToLuaType(), false);
} }
public (LuaType Type, bool Failed) UnaryOperator(object value, LuaType par1, OperatorType op)
{
var method = OperatorHandler.GetUnaryOperator(op, par1.GetCSharpType());
if (method == null)
{
return (new LuaNull(), true);
}
return (method.Invoke(value, new[] {par1.ToCSharpObject()}).ToLuaType(), false);
}
} }
} }

View File

@ -50,6 +50,8 @@ namespace Upsilon.Binder
throw new Exception("Unknown unary operator token: " + operatorToken); throw new Exception("Unknown unary operator token: " + operatorToken);
} }
if (inType == Type.Unknown)
return _operators.FirstOrDefault(op => op.Kind == kind);
return _operators.FirstOrDefault(op => op.Kind == kind && op.InType == inType); return _operators.FirstOrDefault(op => op.Kind == kind && op.InType == inType);
} }
} }

View File

@ -165,9 +165,28 @@ namespace Upsilon.Evaluator
case BoundUnaryOperator.OperatorKind.Identity: case BoundUnaryOperator.OperatorKind.Identity:
return operand; return operand;
case BoundUnaryOperator.OperatorKind.Negation: case BoundUnaryOperator.OperatorKind.Negation:
return -((Number)operand); if (operand.Type == Type.Number)
return -((Number)operand);
else if (operand.Type == Type.UserData)
{
var ud = (UserData) operand;
var (type, failed) = ud.UnaryOperator(operand, OperatorType.UnaryNegation);
if (failed) goto default;
return type;
}
goto default;
case BoundUnaryOperator.OperatorKind.LogicalNegation: case BoundUnaryOperator.OperatorKind.LogicalNegation:
return !(LuaBoolean) operand; if (operand.Type == Type.Boolean)
return !(LuaBoolean) operand;
else if (operand.Type == Type.UserData)
{
var ud = (UserData) operand;
var (type, failed) = ud.UnaryOperator(operand, OperatorType.LogicalNot);
if (failed) goto default;
return type;
}
goto default;
default: default:
throw new Exception("Invalid Unary Operator: " + e.Operator.Kind); throw new Exception("Invalid Unary Operator: " + e.Operator.Kind);
} }

View File

@ -46,6 +46,11 @@ namespace UpsilonTests
return new UserDataHelper(a.Value - b.Value); return new UserDataHelper(a.Value - b.Value);
} }
public static UserDataHelper operator -(UserDataHelper a)
{
return new UserDataHelper(-a.Value);
}
public static UserDataHelper operator *(UserDataHelper a, UserDataHelper b) public static UserDataHelper operator *(UserDataHelper a, UserDataHelper b)
{ {
return new UserDataHelper(a.Value * b.Value); return new UserDataHelper(a.Value * b.Value);
@ -145,5 +150,21 @@ end
Assert.Equal(10, result.Value); Assert.Equal(10, result.Value);
} }
[Fact]
public void TestNegation()
{
const string input = @"
function negate(o1)
return -o1
end
";
var script = new Script(input);
Assert.Empty(script.Diagnostics.Messages);
var o1 = new UserDataHelper(100);
var result = script.EvaluateFunction<UserDataHelper>("negate", new object[] {o1});
Assert.Empty(script.Diagnostics.Messages);
Assert.Equal(-100, result.Value);
}
} }
} }