Work on standard libraries.
- Allows Standard Libraries to work with actual luatypes, to prevent constant back and forth casting - adds ipairs function, doesn't do anything except maintain compatibility with lua - several tests
This commit is contained in:
parent
806b3d5689
commit
c63df3c941
|
@ -1,3 +1,6 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
@ -53,20 +56,32 @@ namespace Upsilon.BaseTypes
|
||||||
|
|
||||||
internal class ScriptMethodInfoFunction : ScriptFunction
|
internal class ScriptMethodInfoFunction : ScriptFunction
|
||||||
{
|
{
|
||||||
public ScriptMethodInfoFunction(UserDataMethod method, object o)
|
public ScriptMethodInfoFunction(UserDataMethod method, object o, bool directTypeManipulation)
|
||||||
{
|
{
|
||||||
_method = method;
|
_method = method;
|
||||||
_object = o;
|
_object = o;
|
||||||
|
_directTypeManipulation = directTypeManipulation;
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly UserDataMethod _method;
|
private readonly UserDataMethod _method;
|
||||||
private readonly object _object;
|
private readonly object _object;
|
||||||
|
private readonly bool _directTypeManipulation;
|
||||||
|
|
||||||
public override ScriptType Run(Diagnostics diagnostics, ScriptType[] variables)
|
public override ScriptType Run(Diagnostics diagnostics, ScriptType[] variables)
|
||||||
{
|
{
|
||||||
var types = variables.Select(x => x.GetCSharpType());
|
var types = _directTypeManipulation
|
||||||
var method = _method.GetMethod(types.ToArray());
|
? variables.Select(x => x.GetType()).ToArray()
|
||||||
var objects = variables.Select(x => x.ToCSharpObject()).ToList();
|
: variables.Select(x => x.GetCSharpType()).ToArray();
|
||||||
|
var method = _method.GetMethod(types);
|
||||||
|
if (method == null)
|
||||||
|
{
|
||||||
|
throw new Exception(
|
||||||
|
$"No valid function found on type '{_object.GetType()}' with name '{_method.Name}' " +
|
||||||
|
$"and parameter types: {string.Join(", ", types.Select(x => $"'{x.Name}'"))}");
|
||||||
|
}
|
||||||
|
var objects = _directTypeManipulation
|
||||||
|
? variables.Select(x => (object) x).ToList()
|
||||||
|
: variables.Select(x => x.ToCSharpObject()).ToList();
|
||||||
var pars = method.GetParameters();
|
var pars = method.GetParameters();
|
||||||
if (pars.Length != objects.Count)
|
if (pars.Length != objects.Count)
|
||||||
{
|
{
|
||||||
|
@ -78,7 +93,10 @@ namespace Upsilon.BaseTypes
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return method.Invoke(_object, objects.ToArray()).ToLuaType();
|
var result = method.Invoke(_object, objects.ToArray());
|
||||||
|
if (_directTypeManipulation)
|
||||||
|
return (ScriptType)result;
|
||||||
|
return result.ToScriptType();
|
||||||
}
|
}
|
||||||
catch (TargetInvocationException e)
|
catch (TargetInvocationException e)
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,7 +6,7 @@ namespace Upsilon.BaseTypes
|
||||||
{
|
{
|
||||||
internal static class TypeConversion
|
internal static class TypeConversion
|
||||||
{
|
{
|
||||||
public static ScriptType ToLuaType(this object o)
|
public static ScriptType ToScriptType(this object o)
|
||||||
{
|
{
|
||||||
if (o is ScriptType type) return type;
|
if (o is ScriptType type) return type;
|
||||||
switch (o)
|
switch (o)
|
||||||
|
|
|
@ -18,7 +18,7 @@ namespace Upsilon.BaseTypes.UserData
|
||||||
var key = index.ToCSharpObject();
|
var key = index.ToCSharpObject();
|
||||||
if (Dictionary.Contains(key))
|
if (Dictionary.Contains(key))
|
||||||
{
|
{
|
||||||
return Dictionary[key].ToLuaType();
|
return Dictionary[key].ToScriptType();
|
||||||
}
|
}
|
||||||
//TODO: log error
|
//TODO: log error
|
||||||
return new ScriptNull();
|
return new ScriptNull();
|
||||||
|
|
|
@ -32,7 +32,7 @@ namespace Upsilon.BaseTypes.UserData
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return List[i].ToLuaType();
|
return List[i].ToScriptType();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Set(Diagnostics diagnostics, TextSpan span, ScriptType index, ScriptType value)
|
public void Set(Diagnostics diagnostics, TextSpan span, ScriptType index, ScriptType value)
|
||||||
|
|
|
@ -30,10 +30,12 @@ namespace Upsilon.BaseTypes.UserData
|
||||||
public bool IsOptional { get; }
|
public bool IsOptional { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string Name { get; }
|
||||||
private List<UserDataMethodPart> MethodParts { get; }
|
private List<UserDataMethodPart> MethodParts { get; }
|
||||||
|
|
||||||
public UserDataMethod(MethodInfo method)
|
public UserDataMethod(MethodInfo method)
|
||||||
{
|
{
|
||||||
|
Name = method.Name;
|
||||||
var part = new UserDataMethodPart(method);
|
var part = new UserDataMethodPart(method);
|
||||||
MethodParts = new List<UserDataMethodPart>()
|
MethodParts = new List<UserDataMethodPart>()
|
||||||
{
|
{
|
||||||
|
|
|
@ -40,15 +40,15 @@ namespace Upsilon.BaseTypes.UserData
|
||||||
member = member.ToLowerInvariant();
|
member = member.ToLowerInvariant();
|
||||||
if (Variables.TryGetValue(member, out var info))
|
if (Variables.TryGetValue(member, out var info))
|
||||||
{
|
{
|
||||||
return (info.GetValue(value).ToLuaType(), false, null);
|
return (info.GetValue(value).ToScriptType(), false, null);
|
||||||
}
|
}
|
||||||
if (Properties.TryGetValue(member, out var property))
|
if (Properties.TryGetValue(member, out var property))
|
||||||
{
|
{
|
||||||
return (property.GetValue(value).ToLuaType(), false, null);
|
return (property.GetValue(value).ToScriptType(), false, null);
|
||||||
}
|
}
|
||||||
if (Methods.TryGetValue(member, out var method))
|
if (Methods.TryGetValue(member, out var method))
|
||||||
{
|
{
|
||||||
return (new ScriptMethodInfoFunction(method, value), false, null);
|
return (new ScriptMethodInfoFunction(method, value, false), false, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (null, true, $"Can't find public member '{member}' on type '{Type}'.");
|
return (null, true, $"Can't find public member '{member}' on type '{Type}'.");
|
||||||
|
@ -85,7 +85,7 @@ namespace Upsilon.BaseTypes.UserData
|
||||||
return (new ScriptNull(), true);
|
return (new ScriptNull(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (method.Invoke(value, new[] {par1.ToCSharpObject(), par2.ToCSharpObject()}).ToLuaType(), false);
|
return (method.Invoke(value, new[] {par1.ToCSharpObject(), par2.ToCSharpObject()}).ToScriptType(), false);
|
||||||
}
|
}
|
||||||
public (ScriptType Type, bool Failed) UnaryOperator(object value, ScriptType par1, OperatorType op)
|
public (ScriptType Type, bool Failed) UnaryOperator(object value, ScriptType par1, OperatorType op)
|
||||||
{
|
{
|
||||||
|
@ -95,7 +95,7 @@ namespace Upsilon.BaseTypes.UserData
|
||||||
return (new ScriptNull(), true);
|
return (new ScriptNull(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (method.Invoke(value, new[] {par1.ToCSharpObject()}).ToLuaType(), false);
|
return (method.Invoke(value, new[] {par1.ToCSharpObject()}).ToScriptType(), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -476,7 +476,7 @@ namespace Upsilon.Evaluator
|
||||||
scope = scopeOwner.EvaluationScope;
|
scope = scopeOwner.EvaluationScope;
|
||||||
}
|
}
|
||||||
|
|
||||||
return indexable.Get(_diagnostics, e.Span, e.Index.ToLuaType(), scope);
|
return indexable.Get(_diagnostics, e.Span, e.Index.ToScriptType(), scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EvaluateTableAssignmentStatement(BoundTableAssigmentStatement e)
|
private void EvaluateTableAssignmentStatement(BoundTableAssigmentStatement e)
|
||||||
|
@ -491,7 +491,7 @@ namespace Upsilon.Evaluator
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
table = EvaluateExpression(((BoundFullStopIndexExpression)e.TableIndexExpression).Expression);
|
table = EvaluateExpression(((BoundFullStopIndexExpression)e.TableIndexExpression).Expression);
|
||||||
index = ((BoundFullStopIndexExpression) e.TableIndexExpression).Index.ToLuaType();
|
index = ((BoundFullStopIndexExpression) e.TableIndexExpression).Index.ToScriptType();
|
||||||
}
|
}
|
||||||
|
|
||||||
var value = EvaluateExpression(e.Value);
|
var value = EvaluateExpression(e.Value);
|
||||||
|
@ -499,7 +499,7 @@ namespace Upsilon.Evaluator
|
||||||
{
|
{
|
||||||
throw new Exception("Cant assign to that");
|
throw new Exception("Cant assign to that");
|
||||||
}
|
}
|
||||||
indexable.Set(_diagnostics, e.Span, index.ToString().ToLuaType(), value);
|
indexable.Set(_diagnostics, e.Span, index.ToString().ToScriptType(), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EvaluateNumericForStatement(BoundNumericForStatement e)
|
private void EvaluateNumericForStatement(BoundNumericForStatement e)
|
||||||
|
@ -550,7 +550,7 @@ namespace Upsilon.Evaluator
|
||||||
{
|
{
|
||||||
var (key, value) = enumerator.Current;
|
var (key, value) = enumerator.Current;
|
||||||
if (e.Variables[0].Name != "_")
|
if (e.Variables[0].Name != "_")
|
||||||
innerEvaluator.Scope.CreateLocal(e.Variables[0], key.ToLuaType());
|
innerEvaluator.Scope.CreateLocal(e.Variables[0], key.ToScriptType());
|
||||||
if (e.Variables[1].Name != "_")
|
if (e.Variables[1].Name != "_")
|
||||||
innerEvaluator.Scope.CreateLocal(e.Variables[1], value);
|
innerEvaluator.Scope.CreateLocal(e.Variables[1], value);
|
||||||
innerEvaluator.EvaluateBoundBlockStatement((BoundBlockStatement) e.Block);
|
innerEvaluator.EvaluateBoundBlockStatement((BoundBlockStatement) e.Block);
|
||||||
|
|
|
@ -69,7 +69,7 @@ namespace Upsilon.Evaluator
|
||||||
{
|
{
|
||||||
foreach (var parameter in parameters)
|
foreach (var parameter in parameters)
|
||||||
{
|
{
|
||||||
luaParameters.Add(parameter.ToLuaType());
|
luaParameters.Add(parameter.ToScriptType());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Convert(Evaluator.Evaluate(Bind(), functionName, luaParameters.ToImmutable()));
|
return Convert(Evaluator.Evaluate(Bind(), functionName, luaParameters.ToImmutable()));
|
||||||
|
@ -103,7 +103,7 @@ namespace Upsilon.Evaluator
|
||||||
{
|
{
|
||||||
foreach (var parameter in parameters)
|
foreach (var parameter in parameters)
|
||||||
{
|
{
|
||||||
luaParameters.Add(parameter.ToLuaType());
|
luaParameters.Add(parameter.ToScriptType());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Convert<T>(Evaluator.Evaluate(Bind(), functionName, luaParameters.ToImmutable()));
|
return Convert<T>(Evaluator.Evaluate(Bind(), functionName, luaParameters.ToImmutable()));
|
||||||
|
|
|
@ -12,36 +12,31 @@ namespace Upsilon.StandardLibraries
|
||||||
{
|
{
|
||||||
internal class BasicFunctions : LuaLibrary
|
internal class BasicFunctions : LuaLibrary
|
||||||
{
|
{
|
||||||
[LuaFunction("assert")]
|
[StandardLibraryScriptFunction("assert")]
|
||||||
public void Assert(bool boolean, string message = null)
|
public void Assert(ScriptBoolean boolean, ScriptString message = null)
|
||||||
{
|
{
|
||||||
if (!boolean)
|
if (!boolean)
|
||||||
{
|
{
|
||||||
Error(message ?? "assertion failed!");
|
Error(message ?? new ScriptString("assertion failed!"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[LuaFunction("error")]
|
[StandardLibraryScriptFunction("error")]
|
||||||
public void Error(string message)
|
public void Error(ScriptString message)
|
||||||
{
|
{
|
||||||
throw new Exception(message);
|
throw new Exception(message.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
[StandardLibraryScriptFunction("ipairs")]
|
||||||
[LuaFunction("ipairs")]
|
public IIterable Pairs(IIterable table)
|
||||||
public ScriptType Pairs(IIterable table)
|
|
||||||
{
|
{
|
||||||
if (!table.Next(out var key, out var next))
|
return table;
|
||||||
{
|
}
|
||||||
return new ScriptNull();
|
|
||||||
}
|
|
||||||
|
|
||||||
return new SimpleScriptTable(new List<ScriptType>() {key, next});
|
[StandardLibraryScriptFunction("tonumber")]
|
||||||
}*/
|
public ScriptNumber ToNumber(ScriptString obj)
|
||||||
|
|
||||||
[LuaFunction("tonumber")]
|
|
||||||
public ScriptNumber ToNumber(string str)
|
|
||||||
{
|
{
|
||||||
|
var str = obj.Value;
|
||||||
if (str.Contains("."))
|
if (str.Contains("."))
|
||||||
{
|
{
|
||||||
return new ScriptNumberDouble(double.Parse(str));
|
return new ScriptNumberDouble(double.Parse(str));
|
||||||
|
|
|
@ -13,10 +13,10 @@ namespace Upsilon.StandardLibraries
|
||||||
var methods = GetType().GetMethods();
|
var methods = GetType().GetMethods();
|
||||||
foreach (var methodInfo in methods)
|
foreach (var methodInfo in methods)
|
||||||
{
|
{
|
||||||
var attr = methodInfo.GetCustomAttribute<LuaFunctionAttribute>();
|
var attr = methodInfo.GetCustomAttribute<StandardLibraryScriptFunctionAttribute>();
|
||||||
if (attr != null)
|
if (attr != null)
|
||||||
{
|
{
|
||||||
dictionary.Add(attr.Name, new ScriptMethodInfoFunction(new UserDataMethod(methodInfo), this));
|
dictionary.Add(attr.Name, new ScriptMethodInfoFunction(new UserDataMethod(methodInfo), this, true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,9 +3,9 @@ using System;
|
||||||
namespace Upsilon.StandardLibraries
|
namespace Upsilon.StandardLibraries
|
||||||
{
|
{
|
||||||
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
|
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
|
||||||
public class LuaFunctionAttribute : Attribute
|
public class StandardLibraryScriptFunctionAttribute : Attribute
|
||||||
{
|
{
|
||||||
public LuaFunctionAttribute(string name)
|
public StandardLibraryScriptFunctionAttribute(string name)
|
||||||
{
|
{
|
||||||
Name = name;
|
Name = name;
|
||||||
}
|
}
|
|
@ -54,7 +54,7 @@ namespace Upsilon.StandardLibraries
|
||||||
|
|
||||||
public static void RegisterStaticVariable(string name, object value)
|
public static void RegisterStaticVariable(string name, object value)
|
||||||
{
|
{
|
||||||
var luaVariable = value.ToLuaType();
|
var luaVariable = value.ToScriptType();
|
||||||
var varSymbol = new VariableSymbol(name, luaVariable.Type, false);
|
var varSymbol = new VariableSymbol(name, luaVariable.Type, false);
|
||||||
BoundScope.AssignToNearest(varSymbol);
|
BoundScope.AssignToNearest(varSymbol);
|
||||||
Scope.AssignToNearest(varSymbol, luaVariable);
|
Scope.AssignToNearest(varSymbol, luaVariable);
|
||||||
|
|
|
@ -25,5 +25,36 @@ namespace UpsilonTests.StandardLibraryTests
|
||||||
Assert.Equal("test_error", e.Message);
|
Assert.Equal("test_error", e.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void IPairsTest()
|
||||||
|
{
|
||||||
|
const string input = @"
|
||||||
|
arr = {100, 56, 28}
|
||||||
|
value = 0
|
||||||
|
for key, val in ipairs(arr) do
|
||||||
|
value = value + val
|
||||||
|
end
|
||||||
|
return value
|
||||||
|
";
|
||||||
|
var script = new Script(input, BoundScope, StaticScope);
|
||||||
|
Assert.Empty(script.Diagnostics.Messages);
|
||||||
|
var result = script.Evaluate<long>();
|
||||||
|
Assert.Empty(script.Diagnostics.Messages);
|
||||||
|
Assert.Equal(184, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ToNumberTest()
|
||||||
|
{
|
||||||
|
const string input = @"
|
||||||
|
return tonumber(""100"")
|
||||||
|
";
|
||||||
|
var script = new Script(input, BoundScope, StaticScope);
|
||||||
|
Assert.Empty(script.Diagnostics.Messages);
|
||||||
|
var result = script.Evaluate<long>();
|
||||||
|
Assert.Empty(script.Diagnostics.Messages);
|
||||||
|
Assert.Equal(100, result);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue