Reworked script function attribute, added initial math library
This commit is contained in:
		| @@ -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) | ||||||
|                 Type       = Type.Function, |                     continue; | ||||||
|                 ResultType = x.ReturnType.GetScriptType() |                 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, | ||||||
|  |                     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()); | ||||||
|   | |||||||
							
								
								
									
										18
									
								
								Upsilon/StandardLibraries/MathLibrary.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								Upsilon/StandardLibraries/MathLibrary.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -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) | ||||||
|         { |         { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user