Added UserData support
This commit is contained in:
parent
7d551b6313
commit
d1b1675bba
|
@ -5,6 +5,7 @@ namespace Upsilon.BaseTypes
|
|||
internal interface IIndexable
|
||||
{
|
||||
LuaType Get(string s, EvaluationScope scope);
|
||||
void Set(string s, LuaType value);
|
||||
}
|
||||
|
||||
internal interface IScopeOwner
|
||||
|
|
|
@ -83,5 +83,10 @@ namespace Upsilon.BaseTypes
|
|||
var i = int.Parse(s);
|
||||
return new LuaString(Value[i - 1].ToString());
|
||||
}
|
||||
|
||||
public void Set(string s, LuaType value)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,3 @@
|
|||
using System;
|
||||
using Upsilon.BaseTypes.Number;
|
||||
|
||||
namespace Upsilon.BaseTypes
|
||||
|
@ -19,12 +18,13 @@ namespace Upsilon.BaseTypes
|
|||
return new NumberDouble(f);
|
||||
case double f:
|
||||
return new NumberDouble(f);
|
||||
|
||||
|
||||
case string s:
|
||||
return new LuaString(s);
|
||||
case null:
|
||||
return new LuaNull();
|
||||
default:
|
||||
throw new Exception();
|
||||
}
|
||||
|
||||
return new UserData.UserData(o);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
using Upsilon.Evaluator;
|
||||
|
||||
namespace Upsilon.BaseTypes.UserData
|
||||
{
|
||||
internal class UserData : LuaType, IIndexable
|
||||
{
|
||||
public UserData(object o)
|
||||
{
|
||||
Value = o;
|
||||
_typeInfo = UserDataTypeHandler.GetTypeInfo(o.GetType());
|
||||
}
|
||||
public override Type Type => Type.UserData;
|
||||
|
||||
private object Value { get; }
|
||||
private readonly UserDataType _typeInfo;
|
||||
|
||||
public override object ToCSharpObject()
|
||||
{
|
||||
return Value;
|
||||
}
|
||||
|
||||
public LuaType Get(string s, EvaluationScope scope)
|
||||
{
|
||||
return _typeInfo.Get(Value, s);
|
||||
}
|
||||
|
||||
public void Set(string s, LuaType value)
|
||||
{
|
||||
_typeInfo.Set(Value, s, value);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Upsilon.BaseTypes.UserData
|
||||
{
|
||||
internal class UserDataType
|
||||
{
|
||||
public UserDataType(System.Type type)
|
||||
{
|
||||
Type = type;
|
||||
Variables = type.GetFields().ToDictionary(x => x.Name, x => x);
|
||||
Properties = type.GetProperties().ToDictionary(x => x.Name, x => x);
|
||||
}
|
||||
|
||||
private System.Type Type { get; }
|
||||
private Dictionary<string, FieldInfo> Variables { get; }
|
||||
private Dictionary<string, PropertyInfo> Properties { get; }
|
||||
|
||||
public LuaType Get(object value, string member)
|
||||
{
|
||||
if (value.GetType() != Type)
|
||||
return null;
|
||||
if (Variables.TryGetValue(member, out var info))
|
||||
{
|
||||
return info.GetValue(value).ToLuaType();
|
||||
}
|
||||
if (Properties.TryGetValue(member, out var property))
|
||||
{
|
||||
return property.GetValue(value).ToLuaType();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void Set(object value, string member, LuaType newValue)
|
||||
{
|
||||
if (value.GetType() != Type)
|
||||
return;
|
||||
if (Variables.TryGetValue(member, out var info))
|
||||
{
|
||||
info.SetValue(value, newValue.ToCSharpObject());
|
||||
}
|
||||
if (Properties.TryGetValue(member, out var property))
|
||||
{
|
||||
property.SetValue(value, newValue.ToCSharpObject());
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace Upsilon.BaseTypes.UserData
|
||||
{
|
||||
public static class UserDataTypeHandler
|
||||
{
|
||||
private static readonly Dictionary<System.Type, UserDataType> _types = new Dictionary<System.Type, UserDataType>();
|
||||
|
||||
public static void LoadType(System.Type t)
|
||||
{
|
||||
var info = new UserDataType(t);
|
||||
_types.Add(t, info);
|
||||
}
|
||||
|
||||
public static void LoadType<T>()
|
||||
{
|
||||
LoadType(typeof(T));
|
||||
}
|
||||
|
||||
internal static UserDataType GetTypeInfo(System.Type t)
|
||||
{
|
||||
return _types[t];
|
||||
}
|
||||
}
|
||||
}
|
|
@ -355,13 +355,11 @@ namespace Upsilon.Evaluator
|
|||
var table = EvaluateExpression(e.TableIndexExpression.Identifier);
|
||||
var index = EvaluateExpression(e.TableIndexExpression.Index);
|
||||
var value = EvaluateExpression(e.Value);
|
||||
if (table.Type != Type.Table)
|
||||
if (!(table is IIndexable indexable))
|
||||
{
|
||||
throw new Exception("Not a table");
|
||||
throw new Exception("Cant assign to that");
|
||||
}
|
||||
|
||||
var t = (LuaTable) table;
|
||||
t.Set(index.ToString(), value);
|
||||
indexable.Set(index.ToString(), value);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -84,7 +84,9 @@ namespace Upsilon.Evaluator
|
|||
|
||||
public T Evaluate<T>()
|
||||
{
|
||||
return Convert<T>(Evaluator.Evaluate(Bind()));
|
||||
var bound = Bind();
|
||||
var evaluate = Evaluator.Evaluate(bound);
|
||||
return Convert<T>(evaluate);
|
||||
}
|
||||
|
||||
public T EvaluateFunction<T>(string functionName, object[] parameters = null)
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using Upsilon.Evaluator;
|
||||
using Xunit;
|
||||
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
using System;
|
||||
using Upsilon.BaseTypes.UserData;
|
||||
using Upsilon.Evaluator;
|
||||
using Xunit;
|
||||
|
||||
namespace UpsilonTests
|
||||
{
|
||||
public class UserDataTests : IClassFixture<UserDataTests.UserDataTestsFixture>
|
||||
{
|
||||
public class UserDataTestsFixture : IDisposable
|
||||
{
|
||||
public UserDataTestsFixture()
|
||||
{
|
||||
UserDataTypeHandler.LoadType<UserDataHelper>();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning disable 414, 649
|
||||
private class UserDataHelper
|
||||
{
|
||||
public string FieldString = "TestField";
|
||||
public string FieldStringSet;
|
||||
}
|
||||
#pragma warning restore 414, 649
|
||||
|
||||
|
||||
[Fact]
|
||||
public void AccessFieldsGet()
|
||||
{
|
||||
var obj = new UserDataHelper();
|
||||
const string input = @"
|
||||
function test(o)
|
||||
return o[""FieldString""]
|
||||
end
|
||||
";
|
||||
var script = new Script(input);
|
||||
Assert.Empty(script.Diagnostics.Messages);
|
||||
var result = script.EvaluateFunction<string>("test", new[] {obj});
|
||||
Assert.Empty(script.Diagnostics.Messages);
|
||||
Assert.Equal("TestField", result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AccessFieldsSet()
|
||||
{
|
||||
var obj = new UserDataHelper();
|
||||
const string input = @"
|
||||
function test(o)
|
||||
o[""FieldStringSet""] = ""Test""
|
||||
end
|
||||
";
|
||||
var script = new Script(input);
|
||||
Assert.Empty(script.Diagnostics.Messages);
|
||||
script.EvaluateFunction("test", new[] {obj});
|
||||
Assert.Empty(script.Diagnostics.Messages);
|
||||
Assert.Equal("Test", obj.FieldStringSet);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
using Upsilon;
|
||||
using Upsilon.Evaluator;
|
||||
|
@ -17,7 +18,6 @@ namespace Ycicle
|
|||
Console.Write("» ");
|
||||
var input = Console.ReadLine();
|
||||
if (input == "exit") return;
|
||||
|
||||
script = script == null ? new Script(input) : Script.ContinueWith(script, input);
|
||||
|
||||
if (script.Diagnostics.Messages.Count > 0)
|
||||
|
@ -32,8 +32,8 @@ namespace Ycicle
|
|||
continue;
|
||||
}
|
||||
//Console.WriteLine(script.PrettyPrintSyntaxTree());
|
||||
var evaluate = script.Evaluate<double>();
|
||||
|
||||
var evaluate = script.Evaluate();
|
||||
if (script.Diagnostics.Messages.Count > 0)
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.Red;
|
||||
|
|
Loading…
Reference in New Issue