Reworked script function attribute, added initial math library
This commit is contained in:
parent
9bd82174f2
commit
ac05647d71
|
@ -2,9 +2,9 @@ using System;
|
||||||
|
|
||||||
namespace Upsilon.BaseTypes.Number
|
namespace Upsilon.BaseTypes.Number
|
||||||
{
|
{
|
||||||
internal abstract class ScriptNumber : ScriptType
|
public abstract class ScriptNumber : ScriptType
|
||||||
{
|
{
|
||||||
protected abstract bool IsFloat { get; }
|
protected internal abstract bool IsFloat { get; }
|
||||||
|
|
||||||
public override Type Type => Type.Number;
|
public override Type Type => Type.Number;
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ namespace Upsilon.BaseTypes.Number
|
||||||
internal class ScriptNumberDouble : ScriptNumber
|
internal class ScriptNumberDouble : ScriptNumber
|
||||||
{
|
{
|
||||||
public double Value { get; }
|
public double Value { get; }
|
||||||
protected override bool IsFloat { get; } = true;
|
protected internal override bool IsFloat { get; } = true;
|
||||||
|
|
||||||
public ScriptNumberDouble(double value)
|
public ScriptNumberDouble(double value)
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,7 +6,7 @@ namespace Upsilon.BaseTypes.Number
|
||||||
internal class ScriptNumberLong : ScriptNumber
|
internal class ScriptNumberLong : ScriptNumber
|
||||||
{
|
{
|
||||||
public long Value { get; set; }
|
public long Value { get; set; }
|
||||||
protected override bool IsFloat { get; } = false;
|
protected internal override bool IsFloat { get; } = false;
|
||||||
|
|
||||||
public ScriptNumberLong(long val)
|
public ScriptNumberLong(long val)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
namespace Upsilon.BaseTypes
|
namespace Upsilon.BaseTypes
|
||||||
{
|
{
|
||||||
internal class ScriptBoolean : ScriptType
|
public class ScriptBoolean : ScriptType
|
||||||
{
|
{
|
||||||
public ScriptBoolean(bool value)
|
public ScriptBoolean(bool value)
|
||||||
{
|
{
|
||||||
|
|
|
@ -19,6 +19,15 @@ namespace Upsilon.BaseTypes.ScriptFunction
|
||||||
_passScopeReference = passScopeReference;
|
_passScopeReference = passScopeReference;
|
||||||
|
|
||||||
ReturnType = _method.ReturnType;
|
ReturnType = _method.ReturnType;
|
||||||
|
|
||||||
|
if (method.GetMethods().First().Attribute != null)
|
||||||
|
{
|
||||||
|
var attr = method.GetMethods().First().Attribute;
|
||||||
|
_directTypeManipulation = attr.DirectScriptManipulation;
|
||||||
|
_passScriptReference = attr.PassScriptReference;
|
||||||
|
_passScopeReference = attr.PassScopeReference;
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly UserDataMethod _method;
|
private readonly UserDataMethod _method;
|
||||||
|
|
|
@ -3,7 +3,7 @@ using Upsilon.Text;
|
||||||
|
|
||||||
namespace Upsilon.BaseTypes.UserData
|
namespace Upsilon.BaseTypes.UserData
|
||||||
{
|
{
|
||||||
internal class GenericUserData : ScriptType, IUserData
|
internal sealed class GenericUserData : ScriptType, IUserData
|
||||||
{
|
{
|
||||||
public GenericUserData(object dictionary)
|
public GenericUserData(object dictionary)
|
||||||
{
|
{
|
||||||
|
@ -12,7 +12,7 @@ namespace Upsilon.BaseTypes.UserData
|
||||||
}
|
}
|
||||||
public override Type Type => Type.UserData;
|
public override Type Type => Type.UserData;
|
||||||
|
|
||||||
protected virtual object Value { get; }
|
private object Value { get; }
|
||||||
private readonly UserDataType _typeInfo;
|
private readonly UserDataType _typeInfo;
|
||||||
|
|
||||||
public override object ToCSharpObject()
|
public override object ToCSharpObject()
|
||||||
|
@ -25,7 +25,7 @@ namespace Upsilon.BaseTypes.UserData
|
||||||
return Value.GetType();
|
return Value.GetType();
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual ScriptType Get(Diagnostics diagnostics, TextSpan span, ScriptType index, EvaluationScope scope)
|
public ScriptType Get(Diagnostics diagnostics, TextSpan span, ScriptType index, EvaluationScope scope)
|
||||||
{
|
{
|
||||||
var s = index.ToCSharpObject().ToString();
|
var s = index.ToCSharpObject().ToString();
|
||||||
var (type, failed, error) = _typeInfo.Get(Value, s);
|
var (type, failed, error) = _typeInfo.Get(Value, s);
|
||||||
|
@ -36,7 +36,7 @@ namespace Upsilon.BaseTypes.UserData
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void Set(Diagnostics diagnostics, TextSpan span, ScriptType index, ScriptType value)
|
public void Set(Diagnostics diagnostics, TextSpan span, ScriptType index, ScriptType value)
|
||||||
{
|
{
|
||||||
var s = index.ToCSharpObject().ToString();
|
var s = index.ToCSharpObject().ToString();
|
||||||
var (failed, error) = _typeInfo.Set(Value, s, value);
|
var (failed, error) = _typeInfo.Set(Value, s, value);
|
||||||
|
|
|
@ -2,6 +2,7 @@ using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Upsilon.Evaluator;
|
using Upsilon.Evaluator;
|
||||||
|
using Upsilon.StandardLibraries;
|
||||||
|
|
||||||
namespace Upsilon.BaseTypes.UserData
|
namespace Upsilon.BaseTypes.UserData
|
||||||
{
|
{
|
||||||
|
@ -13,6 +14,8 @@ namespace Upsilon.BaseTypes.UserData
|
||||||
{
|
{
|
||||||
Method = method;
|
Method = method;
|
||||||
var pars = method.GetParameters();
|
var pars = method.GetParameters();
|
||||||
|
Attribute = (ScriptFunctionAttribute) method.GetCustomAttribute(typeof(ScriptFunctionAttribute));
|
||||||
|
|
||||||
var ls = new List<UserDataMethodParameter>();
|
var ls = new List<UserDataMethodParameter>();
|
||||||
foreach (var parameter in pars)
|
foreach (var parameter in pars)
|
||||||
{
|
{
|
||||||
|
@ -26,6 +29,7 @@ namespace Upsilon.BaseTypes.UserData
|
||||||
}
|
}
|
||||||
|
|
||||||
public MethodInfo Method { get; }
|
public MethodInfo Method { get; }
|
||||||
|
public ScriptFunctionAttribute Attribute { get; }
|
||||||
public UserDataMethodParameter[] Parameters { get; }
|
public UserDataMethodParameter[] Parameters { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Upsilon.BaseTypes.ScriptFunction;
|
using Upsilon.BaseTypes.ScriptFunction;
|
||||||
|
using Upsilon.StandardLibraries;
|
||||||
|
|
||||||
namespace Upsilon.BaseTypes.UserData
|
namespace Upsilon.BaseTypes.UserData
|
||||||
{
|
{
|
||||||
|
@ -16,6 +17,12 @@ namespace Upsilon.BaseTypes.UserData
|
||||||
foreach (var methodInfo in type.GetMethods())
|
foreach (var methodInfo in type.GetMethods())
|
||||||
{
|
{
|
||||||
var commonName = methodInfo.Name.ToLowerInvariant();
|
var commonName = methodInfo.Name.ToLowerInvariant();
|
||||||
|
var attribute = methodInfo.GetCustomAttribute(typeof(ScriptFunctionAttribute));
|
||||||
|
if (attribute is ScriptFunctionAttribute sfa )
|
||||||
|
{
|
||||||
|
commonName = sfa.Name.ToLowerInvariant();
|
||||||
|
}
|
||||||
|
|
||||||
if (Methods.TryGetValue(commonName, out var methodData))
|
if (Methods.TryGetValue(commonName, out var methodData))
|
||||||
{
|
{
|
||||||
methodData.LoadMethodPart(methodInfo);
|
methodData.LoadMethodPart(methodInfo);
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
using Upsilon.BaseTypes;
|
using Upsilon.BaseTypes;
|
||||||
|
using Upsilon.StandardLibraries;
|
||||||
using Type = Upsilon.BaseTypes.Type;
|
using Type = Upsilon.BaseTypes.Type;
|
||||||
|
|
||||||
namespace Upsilon.BoundTypes
|
namespace Upsilon.BoundTypes
|
||||||
|
@ -52,12 +54,25 @@ namespace Upsilon.BoundTypes
|
||||||
{
|
{
|
||||||
obj.Properties.Add(f.Name.ToLowerInvariant(), f);
|
obj.Properties.Add(f.Name.ToLowerInvariant(), f);
|
||||||
}
|
}
|
||||||
var methods = backingType.GetMethods().Select(x => new UserDataBoundMethod()
|
var methods = new List<UserDataBoundMethod>();
|
||||||
|
var backingMethods = backingType.GetMethods();
|
||||||
|
foreach (var backingMethod in backingMethods)
|
||||||
{
|
{
|
||||||
Name = x.Name,
|
if (backingMethod.IsSpecialName)
|
||||||
|
continue;
|
||||||
|
var name = backingMethod.Name;
|
||||||
|
var attribute = backingMethod.GetCustomAttribute(typeof(ScriptFunctionAttribute));
|
||||||
|
if (attribute is ScriptFunctionAttribute sfa )
|
||||||
|
{
|
||||||
|
name = sfa.Name;
|
||||||
|
}
|
||||||
|
methods.Add(new UserDataBoundMethod()
|
||||||
|
{
|
||||||
|
Name = name,
|
||||||
Type = Type.Function,
|
Type = Type.Function,
|
||||||
ResultType = x.ReturnType.GetScriptType()
|
ResultType = backingMethod.ReturnType.GetScriptType()
|
||||||
});
|
});
|
||||||
|
}
|
||||||
foreach (var f in methods)
|
foreach (var f in methods)
|
||||||
{
|
{
|
||||||
obj.Properties.Add(f.Name.ToLowerInvariant(), f);
|
obj.Properties.Add(f.Name.ToLowerInvariant(), f);
|
||||||
|
|
|
@ -13,8 +13,9 @@ namespace Upsilon.StandardLibraries
|
||||||
{
|
{
|
||||||
internal class BasicFunctions : ScriptLibrary
|
internal class BasicFunctions : ScriptLibrary
|
||||||
{
|
{
|
||||||
[StandardLibraryScriptFunction("assert", "Asserts that the parameter passed is true. Throws an exception if it is not true. " +
|
[ScriptFunction("assert", "Asserts that the parameter passed is true. Throws an exception if it is not true. " +
|
||||||
"Can take a message to show in the exception, otherwise throws with message \"assertion failed!\"")]
|
"Can take a message to show in the exception, otherwise throws with message \"assertion failed!\"",
|
||||||
|
directScriptManipulation: true)]
|
||||||
public void Assert(ScriptBoolean boolean, ScriptString message = null)
|
public void Assert(ScriptBoolean boolean, ScriptString message = null)
|
||||||
{
|
{
|
||||||
if (!boolean)
|
if (!boolean)
|
||||||
|
@ -23,26 +24,29 @@ namespace Upsilon.StandardLibraries
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[StandardLibraryScriptFunction("error", "Throw an exception with given error message")]
|
[ScriptFunction("error", "Throw an exception with given error message",
|
||||||
|
directScriptManipulation: true)]
|
||||||
public void Error(ScriptString message)
|
public void Error(ScriptString message)
|
||||||
{
|
{
|
||||||
throw new Exception(message.Value);
|
throw new Exception(message.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
[StandardLibraryScriptFunction("ipairs", "Iterates over an iterable variable, like a table, until it encounters a nil value.")]
|
[ScriptFunction("ipairs", "Iterates over an iterable variable, like a table, until it encounters a nil value.",
|
||||||
|
directScriptManipulation: true)]
|
||||||
public IIterable UpTillNullPairs(IIterable table)
|
public IIterable UpTillNullPairs(IIterable table)
|
||||||
{
|
{
|
||||||
return new UpTillNullPairsScriptIterator(table);
|
return new UpTillNullPairsScriptIterator(table);
|
||||||
}
|
}
|
||||||
|
|
||||||
[StandardLibraryScriptFunction("pairs", "Iterates over an iterable variable, like a table, skipping all nil values.")]
|
[ScriptFunction("pairs", "Iterates over an iterable variable, like a table, skipping all nil values.",
|
||||||
|
directScriptManipulation: true)]
|
||||||
public IIterable Pairs(IIterable table)
|
public IIterable Pairs(IIterable table)
|
||||||
{
|
{
|
||||||
return new PairsScriptIterator(table);
|
return new PairsScriptIterator(table);
|
||||||
}
|
}
|
||||||
|
|
||||||
[StandardLibraryScriptFunction("require", "Loads a module from the module path, using the given script loader.",
|
[ScriptFunction("require", "Loads a module from the module path, using the given script loader.",
|
||||||
true)]
|
true, true)]
|
||||||
public ScriptType Require(Script script, ScriptString fileName)
|
public ScriptType Require(Script script, ScriptString fileName)
|
||||||
{
|
{
|
||||||
var file = fileName.Value;
|
var file = fileName.Value;
|
||||||
|
@ -57,7 +61,7 @@ namespace Upsilon.StandardLibraries
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[StandardLibraryScriptFunction("tonumber", "Parses a string to a number.")]
|
[ScriptFunction("tonumber", "Parses a string to a number.", directScriptManipulation: true)]
|
||||||
public ScriptNumber ToNumber(ScriptString obj)
|
public ScriptNumber ToNumber(ScriptString obj)
|
||||||
{
|
{
|
||||||
var str = obj.Value;
|
var str = obj.Value;
|
||||||
|
@ -71,13 +75,13 @@ namespace Upsilon.StandardLibraries
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[StandardLibraryScriptFunction("tostring", "Returns the string value of the given object.")]
|
[ScriptFunction("tostring", "Returns the string value of the given object.", directScriptManipulation: true)]
|
||||||
public ScriptString ToString(ScriptType obj)
|
public ScriptString ToString(ScriptType obj)
|
||||||
{
|
{
|
||||||
return new ScriptString(obj.ToString());
|
return new ScriptString(obj.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
[StandardLibraryScriptFunction("type", "Returns the type of the given object as a string.")]
|
[ScriptFunction("type", "Returns the type of the given object as a string.", directScriptManipulation: true)]
|
||||||
public ScriptString Type(ScriptType obj)
|
public ScriptString Type(ScriptType obj)
|
||||||
{
|
{
|
||||||
return new ScriptString(obj.Type.ToString());
|
return new ScriptString(obj.Type.ToString());
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
using System;
|
||||||
|
using Upsilon.BaseTypes.Number;
|
||||||
|
|
||||||
|
namespace Upsilon.StandardLibraries
|
||||||
|
{
|
||||||
|
internal class MathLibrary
|
||||||
|
{
|
||||||
|
[ScriptFunction("abs", "Returns the absolute value of x. (integer/float)", directScriptManipulation: true)]
|
||||||
|
public ScriptNumber Absolute(ScriptNumber a)
|
||||||
|
{
|
||||||
|
if (a.IsFloat)
|
||||||
|
{
|
||||||
|
return new ScriptNumberDouble(Math.Abs(((ScriptNumberDouble) a).Value));
|
||||||
|
}
|
||||||
|
return new ScriptNumberLong(Math.Abs(((ScriptNumberLong) a).Value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,19 +3,21 @@ using System;
|
||||||
namespace Upsilon.StandardLibraries
|
namespace Upsilon.StandardLibraries
|
||||||
{
|
{
|
||||||
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
|
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
|
||||||
public class StandardLibraryScriptFunctionAttribute : Attribute
|
public class ScriptFunctionAttribute : Attribute
|
||||||
{
|
{
|
||||||
public StandardLibraryScriptFunctionAttribute(string name, string comment = null,
|
public ScriptFunctionAttribute(string name, string comment = null,
|
||||||
bool passScriptReference = false, bool passScopeReference = false)
|
bool directScriptManipulation = false, bool passScriptReference = false, bool passScopeReference = false)
|
||||||
{
|
{
|
||||||
Name = name;
|
Name = name;
|
||||||
Comment = comment;
|
Comment = comment;
|
||||||
|
DirectScriptManipulation = directScriptManipulation;
|
||||||
PassScriptReference = passScriptReference;
|
PassScriptReference = passScriptReference;
|
||||||
PassScopeReference = passScopeReference;
|
PassScopeReference = passScopeReference;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Name { get; }
|
public string Name { get; }
|
||||||
public string Comment { get; }
|
public string Comment { get; }
|
||||||
|
public bool DirectScriptManipulation { get; }
|
||||||
public bool PassScriptReference { get; }
|
public bool PassScriptReference { get; }
|
||||||
public bool PassScopeReference { get; }
|
public bool PassScopeReference { get; }
|
||||||
}
|
}
|
|
@ -14,7 +14,7 @@ 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<StandardLibraryScriptFunctionAttribute>();
|
var attr = methodInfo.GetCustomAttribute<ScriptFunctionAttribute>();
|
||||||
if (attr != null)
|
if (attr != null)
|
||||||
{
|
{
|
||||||
dictionary.Add(attr.Name, new LoadedStandardFunction()
|
dictionary.Add(attr.Name, new LoadedStandardFunction()
|
||||||
|
|
|
@ -6,6 +6,7 @@ using System.Linq;
|
||||||
using Upsilon.BaseTypes;
|
using Upsilon.BaseTypes;
|
||||||
using Upsilon.BaseTypes.Number;
|
using Upsilon.BaseTypes.Number;
|
||||||
using Upsilon.BaseTypes.ScriptTypeInterfaces;
|
using Upsilon.BaseTypes.ScriptTypeInterfaces;
|
||||||
|
using Upsilon.BaseTypes.UserData;
|
||||||
using Upsilon.Binder;
|
using Upsilon.Binder;
|
||||||
using Upsilon.Binder.VariableSymbols;
|
using Upsilon.Binder.VariableSymbols;
|
||||||
using Upsilon.BoundTypes;
|
using Upsilon.BoundTypes;
|
||||||
|
@ -68,6 +69,12 @@ namespace Upsilon.StandardLibraries
|
||||||
};
|
};
|
||||||
boundFuncs.Add(func.Key, functionSymbol);
|
boundFuncs.Add(func.Key, functionSymbol);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UserDataTypeHandler.LoadType<MathLibrary>();
|
||||||
|
funcs.Add("math", new MathLibrary().ToScriptType());
|
||||||
|
boundFuncs.Add("math",
|
||||||
|
new FunctionParameterSymbol("math", BoundTypeHandler.GetTypeDefinition(typeof(MathLibrary))));
|
||||||
|
|
||||||
var scope = new EvaluationScope(funcs);
|
var scope = new EvaluationScope(funcs);
|
||||||
var boundScope = new BoundScope(boundFuncs, null);
|
var boundScope = new BoundScope(boundFuncs, null);
|
||||||
return (scope, boundScope);
|
return (scope, boundScope);
|
||||||
|
|
|
@ -50,7 +50,7 @@ namespace UpsilonTests.GeneralTests
|
||||||
[Theory]
|
[Theory]
|
||||||
[InlineData("1/1", 1)]
|
[InlineData("1/1", 1)]
|
||||||
[InlineData("1000 / 10", 100)]
|
[InlineData("1000 / 10", 100)]
|
||||||
[InlineData("656486 / 5146", 127)]
|
[InlineData("656486 / 5146", 127.57209483)]
|
||||||
[InlineData("656486 / 5146.0", 127.57209483)]
|
[InlineData("656486 / 5146.0", 127.57209483)]
|
||||||
public void Divison(string input, double expectedOutput)
|
public void Divison(string input, double expectedOutput)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue