Skip to content

Commit b6799bb

Browse files
committed
Update built-in libraries for script
1 parent 8027c40 commit b6799bb

15 files changed

+538
-448
lines changed

JSchema/RelogicLabs/JSchema/Exceptions/CommonException.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System.Diagnostics;
12
using RelogicLabs.JSchema.Message;
23
using RelogicLabs.JSchema.Utilities;
34
using static System.Environment;
@@ -37,7 +38,7 @@ public void SetAttribute(string name, string value)
3738

3839
private static string CaptureStackTrace()
3940
{
40-
var stackTrace = new System.Diagnostics.StackTrace(3, true);
41+
var stackTrace = new StackTrace(3, true);
4142
var frames = stackTrace.GetFrames();
4243
var start = 0;
4344
for(var i = start; i < frames.Length; i++)
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using RelogicLabs.JSchema.Message;
2+
3+
namespace RelogicLabs.JSchema.Exceptions;
4+
5+
public class MethodNotFoundException : ScriptRuntimeException
6+
{
7+
public MethodNotFoundException(string code, string message, Exception? innerException = null)
8+
: base(code, message, innerException) { }
9+
public MethodNotFoundException(ErrorDetail detail, Exception? innerException = null)
10+
: base(detail, innerException) { }
11+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using RelogicLabs.JSchema.Message;
2+
3+
namespace RelogicLabs.JSchema.Exceptions;
4+
5+
public class UpdateNotSupportedException : CommonException
6+
{
7+
public UpdateNotSupportedException(string code, string message, Exception? innerException = null)
8+
: base(code, message, innerException) { }
9+
protected UpdateNotSupportedException(ErrorDetail detail, Exception? innerException = null)
10+
: base(detail, innerException) { }
11+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
using RelogicLabs.JSchema.Engine;
2+
using RelogicLabs.JSchema.Script;
3+
using RelogicLabs.JSchema.Types;
4+
using static RelogicLabs.JSchema.Engine.ScriptTreeHelper;
5+
using static RelogicLabs.JSchema.Message.ErrorCode;
6+
using static RelogicLabs.JSchema.Types.IEUndefined;
7+
8+
namespace RelogicLabs.JSchema.Library;
9+
10+
internal sealed class ArrayLibrary : CommonLibrary
11+
{
12+
private const string Length_M0 = "length#0";
13+
private const string Find_Bn = "find";
14+
private const string Find_M1 = "find#1";
15+
private const string Find_M2 = "find#2";
16+
private const string Fill_Bn = "fill";
17+
private const string Fill_M2 = "fill#2";
18+
private const string Copy_M0 = "copy#0";
19+
20+
private const string Start_Id = "start";
21+
private const string Length_Id = "length";
22+
23+
public new static ArrayLibrary Instance { get; } = new();
24+
protected override EType Type => EType.ARRAY;
25+
26+
private ArrayLibrary()
27+
{
28+
AddMethod(Length_M0, LengthMethod);
29+
AddMethod(Find_M1, FindMethod1);
30+
AddMethod(Find_M2, FindMethod2);
31+
AddMethod(Fill_M2, FillMethod);
32+
AddMethod(Copy_M0, CopyMethod);
33+
}
34+
35+
private static GInteger LengthMethod(IEValue self, List<IEValue> arguments, ScriptScope scope)
36+
=> GInteger.From(((IEArray) self).Count);
37+
38+
private static IEValue FindMethod1(IEValue self, List<IEValue> arguments, ScriptScope scope)
39+
{
40+
var runtime = scope.GetRuntime();
41+
var array = (IEArray) self;
42+
var value = arguments[0];
43+
for(var i = 0; i < array.Count; i++)
44+
if(AreEqual(array.Get(i), value, runtime)) return GInteger.From(i);
45+
return UNDEFINED;
46+
}
47+
48+
private static IEValue FindMethod2(IEValue self, List<IEValue> arguments, ScriptScope scope)
49+
{
50+
var runtime = scope.GetRuntime();
51+
var array = (IEArray) self;
52+
var value = arguments[0];
53+
var start = arguments[1] is IEInteger s ? (int) s.Value
54+
: throw FailOnInvalidArgumentType(AFND01, arguments[1], Find_Bn, Start_Id, self);
55+
for(var i = start; i < array.Count; i++)
56+
if(AreEqual(array.Get(i), value, runtime)) return GInteger.From(i);
57+
return UNDEFINED;
58+
}
59+
60+
private static IEValue FillMethod(IEValue self, List<IEValue> arguments, ScriptScope scope)
61+
{
62+
var length = arguments[1] is IEInteger l ? (int) l.Value
63+
: throw FailOnInvalidArgumentType(FILL01, arguments[1], Fill_Bn, Length_Id, self);
64+
return GArray.FilledFrom(arguments[0], length);
65+
}
66+
67+
private static IEValue CopyMethod(IEValue self, List<IEValue> arguments, ScriptScope scope)
68+
=> new GArray(((IEArray) self).Values);
69+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
using RelogicLabs.JSchema.Engine;
2+
using RelogicLabs.JSchema.Exceptions;
3+
using RelogicLabs.JSchema.Script;
4+
using RelogicLabs.JSchema.Types;
5+
using RelogicLabs.JSchema.Utilities;
6+
using static RelogicLabs.JSchema.Engine.ScriptTreeHelper;
7+
using static RelogicLabs.JSchema.Message.ErrorCode;
8+
using static RelogicLabs.JSchema.Tree.IEFunction;
9+
10+
namespace RelogicLabs.JSchema.Library;
11+
12+
internal class CommonLibrary
13+
{
14+
private const string Type_M0 = "type#0";
15+
private const string String_M0 = "string#0";
16+
private readonly Dictionary<string, MethodEvaluator> _methods;
17+
18+
public static CommonLibrary Instance { get; } = new();
19+
protected virtual EType Type => EType.ANY;
20+
21+
private protected CommonLibrary()
22+
{
23+
_methods = new Dictionary<string, MethodEvaluator>(20);
24+
AddMethod(Type_M0, TypeMethod);
25+
AddMethod(String_M0, StringMethod);
26+
}
27+
28+
public MethodEvaluator GetMethod(string name, int argCount)
29+
=> _methods.TryGetValue($"{name}#{argCount}")
30+
?? _methods.TryGetValue($"{name}#{VariadicArity}")
31+
?? throw FailOnMethodNotFound(name, argCount, Type);
32+
33+
protected void AddMethod(string name, MethodEvaluator evaluator)
34+
=> _methods.Add(name, evaluator);
35+
36+
private static GString TypeMethod(IEValue self, List<IEValue> arguments, ScriptScope scope)
37+
=> GString.From(self.Type.Name);
38+
39+
private static GString StringMethod(IEValue self, List<IEValue> arguments, ScriptScope scope)
40+
=> GString.From(Stringify(self));
41+
42+
private static ScriptCommonException FailOnMethodNotFound(string name, int argCount, EType type)
43+
=> new(MNVK01, $"Method '{name}' with {argCount} parameter(s) of {type} not found");
44+
45+
protected static ScriptArgumentException FailOnInvalidArgumentType(string code, IEValue argument,
46+
string method, string parameter, IEValue self)
47+
=> new(code, $"Invalid {argument.Type} argument for '{parameter}' parameter in '{
48+
method}' method of {self.Type}");
49+
}

JSchema/RelogicLabs/JSchema/Library/NEvaluator.cs renamed to JSchema/RelogicLabs/JSchema/Library/FunctionEvaluator.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@
33

44
namespace RelogicLabs.JSchema.Library;
55

6-
internal delegate IEValue NEvaluator(ScopeContext scope, List<IEValue> arguments);
6+
internal delegate IEValue FunctionEvaluator(ScriptScope scope, List<IEValue> arguments);

JSchema/RelogicLabs/JSchema/Library/NFunction.cs renamed to JSchema/RelogicLabs/JSchema/Library/LibraryFunction.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@
77

88
namespace RelogicLabs.JSchema.Library;
99

10-
internal sealed class NFunction : IRFunction
10+
internal sealed class LibraryFunction : IRFunction
1111
{
1212
public GParameter[] Parameters { get; }
1313
public bool Variadic { get; }
14-
public NEvaluator Body { get; }
14+
public FunctionEvaluator Body { get; }
1515

16-
public NFunction(NEvaluator body, params string[] parameters)
16+
public LibraryFunction(FunctionEvaluator body, params string[] parameters)
1717
{
1818
Parameters = ToParameters(parameters);
1919
Variadic = HasVariadic(Parameters);
@@ -23,12 +23,12 @@ public NFunction(NEvaluator body, params string[] parameters)
2323
private static GParameter[] ToParameters(params string[] names)
2424
=> names.Select(static n => new GParameter(n)).ToArray();
2525

26-
public ScopeContext Bind(ScopeContext parentScope, List<IEValue> arguments)
26+
public ScriptScope Bind(ScriptScope parentScope, List<IEValue> arguments)
2727
{
28-
AreCompatible(this, arguments, FUNS06);
28+
AreCompatible(this, arguments, FNVK03);
2929
return parentScope;
3030
}
3131

32-
public IEValue Invoke(ScopeContext functionScope, List<IEValue> arguments)
32+
public IEValue Invoke(ScriptScope functionScope, List<IEValue> arguments)
3333
=> Body(functionScope, arguments);
3434
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
using RelogicLabs.JSchema.Engine;
2+
using RelogicLabs.JSchema.Types;
3+
4+
namespace RelogicLabs.JSchema.Library;
5+
6+
internal delegate IEValue MethodEvaluator(IEValue self, List<IEValue> arguments, ScriptScope scope);
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
using RelogicLabs.JSchema.Engine;
2+
using RelogicLabs.JSchema.Script;
3+
using RelogicLabs.JSchema.Types;
4+
using static RelogicLabs.JSchema.Message.ErrorCode;
5+
6+
namespace RelogicLabs.JSchema.Library;
7+
8+
internal sealed class NumberLibrary : CommonLibrary
9+
{
10+
private const string Pow_Bn = "pow";
11+
private const string Pow_M1 = "pow#1";
12+
private const string Log_M0 = "log#0";
13+
private const string Ceil_M0 = "ceil#0";
14+
private const string Floor_M0 = "floor#0";
15+
private const string Copy_M0 = "copy#0";
16+
17+
private const string Value_Id = "value";
18+
19+
public new static NumberLibrary Instance { get; } = new();
20+
protected override EType Type => EType.NUMBER;
21+
22+
private NumberLibrary()
23+
{
24+
AddMethod(Pow_M1, PowMethod);
25+
AddMethod(Log_M0, LogMethod);
26+
AddMethod(Ceil_M0, CeilMethod);
27+
AddMethod(Floor_M0, FloorMethod);
28+
AddMethod(Copy_M0, CopyMethod);
29+
}
30+
31+
private static GDouble PowMethod(IEValue self, List<IEValue> arguments, ScriptScope scope)
32+
{
33+
var value = arguments[0] is IENumber v ? v.ToDouble()
34+
: throw FailOnInvalidArgumentType(POWR01, arguments[0], Pow_Bn, Value_Id, self);
35+
return GDouble.From(Math.Pow(((IENumber) self).ToDouble(), value));
36+
}
37+
38+
private static GDouble LogMethod(IEValue self, List<IEValue> arguments, ScriptScope scope)
39+
=> GDouble.From(Math.Log(((IENumber) self).ToDouble()));
40+
41+
private static GInteger CeilMethod(IEValue self, List<IEValue> arguments, ScriptScope scope)
42+
=> GInteger.From((long) Math.Ceiling(((IENumber) self).ToDouble()));
43+
44+
private static GInteger FloorMethod(IEValue self, List<IEValue> arguments, ScriptScope scope)
45+
=> GInteger.From((long) Math.Floor(((IENumber) self).ToDouble()));
46+
47+
private static IEValue CopyMethod(IEValue self, List<IEValue> arguments, ScriptScope scope)
48+
{
49+
if(self is IEInteger i) return GInteger.From(i.Value);
50+
if(self is IENumber n) return GDouble.From(n.ToDouble());
51+
throw new InvalidOperationException("Invalid runtime state");
52+
}
53+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using RelogicLabs.JSchema.Engine;
2+
using RelogicLabs.JSchema.Script;
3+
using RelogicLabs.JSchema.Types;
4+
5+
namespace RelogicLabs.JSchema.Library;
6+
7+
internal sealed class ObjectLibrary : CommonLibrary
8+
{
9+
private const string Size_M0 = "size#0";
10+
private const string Length_M0 = "length#0";
11+
private const string Copy_M0 = "copy#0";
12+
13+
public new static ObjectLibrary Instance { get; } = new();
14+
protected override EType Type => EType.OBJECT;
15+
16+
private ObjectLibrary()
17+
{
18+
AddMethod(Size_M0, SizeMethod);
19+
AddMethod(Length_M0, SizeMethod);
20+
AddMethod(Copy_M0, CopyMethod);
21+
}
22+
23+
private static GInteger SizeMethod(IEValue self, List<IEValue> arguments, ScriptScope scope)
24+
=> GInteger.From(((IEObject) self).Count);
25+
26+
private static GObject CopyMethod(IEValue self, List<IEValue> arguments, ScriptScope scope)
27+
=> new((IEObject) self);
28+
}

0 commit comments

Comments
 (0)