Added UserData support
This commit is contained in:
parent
7d551b6313
commit
d1b1675bba
|
@ -5,6 +5,7 @@ namespace Upsilon.BaseTypes
|
||||||
internal interface IIndexable
|
internal interface IIndexable
|
||||||
{
|
{
|
||||||
LuaType Get(string s, EvaluationScope scope);
|
LuaType Get(string s, EvaluationScope scope);
|
||||||
|
void Set(string s, LuaType value);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal interface IScopeOwner
|
internal interface IScopeOwner
|
||||||
|
|
|
@ -83,5 +83,10 @@ namespace Upsilon.BaseTypes
|
||||||
var i = int.Parse(s);
|
var i = int.Parse(s);
|
||||||
return new LuaString(Value[i - 1].ToString());
|
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;
|
using Upsilon.BaseTypes.Number;
|
||||||
|
|
||||||
namespace Upsilon.BaseTypes
|
namespace Upsilon.BaseTypes
|
||||||
|
@ -19,12 +18,13 @@ namespace Upsilon.BaseTypes
|
||||||
return new NumberDouble(f);
|
return new NumberDouble(f);
|
||||||
case double f:
|
case double f:
|
||||||
return new NumberDouble(f);
|
return new NumberDouble(f);
|
||||||
|
case string s:
|
||||||
|
return new LuaString(s);
|
||||||
|
case null:
|
||||||
|
return new LuaNull();
|
||||||
default:
|
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 table = EvaluateExpression(e.TableIndexExpression.Identifier);
|
||||||
var index = EvaluateExpression(e.TableIndexExpression.Index);
|
var index = EvaluateExpression(e.TableIndexExpression.Index);
|
||||||
var value = EvaluateExpression(e.Value);
|
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");
|
||||||
}
|
}
|
||||||
|
indexable.Set(index.ToString(), value);
|
||||||
var t = (LuaTable) table;
|
|
||||||
t.Set(index.ToString(), value);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -84,7 +84,9 @@ namespace Upsilon.Evaluator
|
||||||
|
|
||||||
public T Evaluate<T>()
|
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)
|
public T EvaluateFunction<T>(string functionName, object[] parameters = null)
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
using Upsilon.Evaluator;
|
using Upsilon.Evaluator;
|
||||||
using Xunit;
|
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;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Upsilon;
|
using Upsilon;
|
||||||
using Upsilon.Evaluator;
|
using Upsilon.Evaluator;
|
||||||
|
@ -17,7 +18,6 @@ namespace Ycicle
|
||||||
Console.Write("» ");
|
Console.Write("» ");
|
||||||
var input = Console.ReadLine();
|
var input = Console.ReadLine();
|
||||||
if (input == "exit") return;
|
if (input == "exit") return;
|
||||||
|
|
||||||
script = script == null ? new Script(input) : Script.ContinueWith(script, input);
|
script = script == null ? new Script(input) : Script.ContinueWith(script, input);
|
||||||
|
|
||||||
if (script.Diagnostics.Messages.Count > 0)
|
if (script.Diagnostics.Messages.Count > 0)
|
||||||
|
@ -32,8 +32,8 @@ namespace Ycicle
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
//Console.WriteLine(script.PrettyPrintSyntaxTree());
|
//Console.WriteLine(script.PrettyPrintSyntaxTree());
|
||||||
|
var evaluate = script.Evaluate<double>();
|
||||||
|
|
||||||
var evaluate = script.Evaluate();
|
|
||||||
if (script.Diagnostics.Messages.Count > 0)
|
if (script.Diagnostics.Messages.Count > 0)
|
||||||
{
|
{
|
||||||
Console.ForegroundColor = ConsoleColor.Red;
|
Console.ForegroundColor = ConsoleColor.Red;
|
||||||
|
|
Loading…
Reference in New Issue