Skip to content

Commit 696031d

Browse files
committed
Update script runtime and interpreter engine
1 parent b156aa4 commit 696031d

19 files changed

+693
-504
lines changed

JSchema/RelogicLabs/JSchema/Engine/Evaluator.cs

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

33
namespace RelogicLabs.JSchema.Engine;
44

5-
internal delegate IEValue Evaluator(ScopeContext scope);
5+
internal delegate IEValue Evaluator(ScriptScope scope);

JSchema/RelogicLabs/JSchema/Engine/ScriptErrorHelper.cs

Lines changed: 73 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -5,144 +5,160 @@
55
using RelogicLabs.JSchema.Types;
66
using static RelogicLabs.JSchema.Message.ErrorCode;
77
using static RelogicLabs.JSchema.Message.MessageFormatter;
8-
using static RelogicLabs.JSchema.Message.OutlineFormatter;
98

109
namespace RelogicLabs.JSchema.Engine;
1110

1211
internal static class ScriptErrorHelper
1312
{
14-
internal const string ADDITION = "addition";
15-
internal const string SUBTRACTION = "subtraction";
16-
internal const string MULTIPLICATION = "multiplication";
17-
internal const string DIVISION = "division";
18-
internal const string INDEX = "index";
19-
internal const string RANGE = "range";
20-
internal const string COMPARISON = "comparison";
21-
internal const string PROPERTY = "property access";
22-
internal const string INCREMENT = "increment";
23-
internal const string DECREMENT = "decrement";
24-
internal const string NEGATION = "negation";
13+
internal const string OpAddition = "addition";
14+
internal const string OpSubtraction = "subtraction";
15+
internal const string OpMultiplication = "multiplication";
16+
internal const string OpDivision = "division";
17+
internal const string OpModulus = "modulus";
18+
internal const string OpUnaryPlus = "unary plus";
19+
internal const string OpUnaryMinus = "unary minus";
20+
internal const string OpBracket = "bracket";
21+
internal const string OpIndex = "index";
22+
internal const string OpRange = "range";
23+
internal const string OpRangeSetup = "range setup";
24+
internal const string OpComparison = "comparison";
25+
internal const string OpProperty = "property access";
26+
internal const string OpIncrement = "increment";
27+
internal const string OpDecrement = "decrement";
28+
internal const string OpBracketedAssignment = "bracketed assignment";
29+
internal const string OpPropertyAssignment = "property assignment";
30+
internal const string OpAdditionAssignment = "addition assignment";
31+
internal const string OpSubtractionAssignment = "subtraction assignment";
32+
internal const string OpMultiplicationAssignment = "multiplication assignment";
33+
internal const string OpDivisionAssignment = "division assignment";
34+
internal const string OpModulusAssignment = "modulus assignment";
2535

2636
internal static InvalidFunctionException FailOnDuplicateParameterName(ITerminalNode node)
27-
=> new(FormatForSchema(FUNS01, $"Duplicate parameter name '{node.GetText()}'", node.Symbol));
37+
=> new(FormatForSchema(FPRM01, $"Duplicate parameter name '{node.GetText()}'", node.Symbol));
2838

2939
internal static ScriptRuntimeException FailOnInvalidReturnType(IEValue value, IToken token)
30-
=> new(FormatForSchema(RETN01, $"Invalid return type {
31-
value.Type} for constraint function", token));
40+
=> new(FormatForSchema(RETN01, $"Invalid return type {value.Type} for constraint function",
41+
token));
3242

33-
internal static ScriptRuntimeException FailOnPropertyNotExist(IEObject source, string property,
34-
IToken token)
35-
=> new(FormatForSchema(PRPS02, $"Property '{property}' not exist in readonly {
36-
source.Type}", token));
43+
internal static ScriptRuntimeException FailOnPropertyNotExist(string code, IEObject instance,
44+
string property, IToken token)
45+
=> new(FormatForSchema(code, $"Property '{property}' not exist in {instance.Type}", token));
3746

38-
internal static Exception FailOnIndexOutOfBounds(IEString source, IEInteger index, IToken token,
47+
internal static Exception FailOnIndexOutOfBounds(IEString value, IEInteger index, IToken token,
3948
Exception innerException)
4049
{
4150
var indexValue = index.Value;
42-
if(indexValue < 0) return new ScriptRuntimeException(FormatForSchema(INDX03,
51+
if(indexValue < 0) return new ScriptRuntimeException(FormatForSchema(SIDX02,
4352
$"Invalid negative index {index} for string starts at 0", token), innerException);
44-
var length = source.Length;
45-
if(indexValue >= length) return new ScriptRuntimeException(FormatForSchema(INDX02,
53+
var length = value.Length;
54+
if(indexValue >= length) return new ScriptRuntimeException(FormatForSchema(SIDX01,
4655
$"Index {index} out of bounds for string length {length}", token), innerException);
4756
return innerException;
4857
}
4958

50-
internal static Exception FailOnIndexOutOfBounds(IEArray array, IEInteger index, IToken token,
59+
internal static Exception FailOnIndexOutOfBounds(IEArray value, IEInteger index, IToken token,
5160
Exception innerException)
5261
{
5362
var indexValue = index.Value;
54-
if(indexValue < 0) return new ScriptRuntimeException(FormatForSchema(INDX05,
63+
if(indexValue < 0) return new ScriptRuntimeException(FormatForSchema(AIDX02,
5564
$"Invalid negative index {index} for array starts at 0", token), innerException);
56-
var count = array.Count;
57-
if(indexValue >= count) return new ScriptRuntimeException(FormatForSchema(INDX04,
65+
var count = value.Count;
66+
if(indexValue >= count) return new ScriptRuntimeException(FormatForSchema(AIDX01,
5867
$"Index {index} out of bounds for array length {count}", token), innerException);
5968
return innerException;
6069
}
6170

62-
internal static Exception FailOnInvalidRangeIndex(IEString source, GRange range, IToken token,
71+
internal static Exception FailOnInvalidRangeIndex(IEString value, GRange range, IToken token,
6372
Exception innerException)
6473
{
65-
int length = source.Length, start = range.GetStart(length), end = range.GetEnd(length);
66-
if(start < 0 || start > length) throw new ScriptRuntimeException(FormatForSchema(RNGS04,
74+
int length = value.Length, start = range.GetStart(length), end = range.GetEnd(length);
75+
if(start < 0 || start > length) throw new ScriptRuntimeException(FormatForSchema(SRNG01,
6776
$"Range start index {start} out of bounds for string length {length}",
6877
token), innerException);
69-
if(end < 0 || end > length) return new ScriptRuntimeException(FormatForSchema(RNGS05,
78+
if(end < 0 || end > length) return new ScriptRuntimeException(FormatForSchema(SRNG02,
7079
$"Range end index {end} out of bounds for string length {length}",
7180
token), innerException);
72-
if(start > end) return new ScriptRuntimeException(FormatForSchema(RNGS06,
73-
$"Range start index {start} > end index {end} for string {CreateOutline(source)}",
81+
if(start > end) return new ScriptRuntimeException(FormatForSchema(SRNG03,
82+
$"Range start index {start} > end index {end} for string length {length}",
7483
token), innerException);
7584
return innerException;
7685
}
7786

78-
internal static Exception FailOnInvalidRangeIndex(IEArray array, GRange range, IToken token,
87+
internal static Exception FailOnInvalidRangeIndex(IEArray value, GRange range, IToken token,
7988
Exception innerException)
8089
{
81-
int count = array.Count, start = range.GetStart(count), end = range.GetEnd(count);
82-
if(start < 0 || start > count) throw new ScriptRuntimeException(FormatForSchema(RNGS07,
90+
int count = value.Count, start = range.GetStart(count), end = range.GetEnd(count);
91+
if(start < 0 || start > count) throw new ScriptRuntimeException(FormatForSchema(ARNG01,
8392
$"Range start index {start} out of bounds for array length {count}",
8493
token), innerException);
85-
if(end < 0 || end > count) return new ScriptRuntimeException(FormatForSchema(RNGS08,
94+
if(end < 0 || end > count) return new ScriptRuntimeException(FormatForSchema(ARNG02,
8695
$"Range end index {end} out of bounds for array length {count}",
8796
token), innerException);
88-
if(start > end) return new ScriptRuntimeException(FormatForSchema(RNGS09,
89-
$"Range start index {start} > end index {end} for array {CreateOutline(array)}",
97+
if(start > end) return new ScriptRuntimeException(FormatForSchema(ARNG03,
98+
$"Range start index {start} > end index {end} for array length {count}",
9099
token), innerException);
91100
return innerException;
92101
}
93102

94103
internal static ScriptRuntimeException FailOnInvalidLValueIncrement(string code, IToken token)
95-
=> new(FormatForSchema(code, "Invalid l-value for increment", token));
104+
=> new(FormatForSchema(code, "Invalid l-value for increment (readonly)", token));
96105

97106
internal static ScriptRuntimeException FailOnInvalidLValueDecrement(string code, IToken token)
98-
=> new(FormatForSchema(code, "Invalid l-value for decrement", token));
107+
=> new(FormatForSchema(code, "Invalid l-value for decrement (readonly)", token));
99108

100-
internal static ScriptRuntimeException FailOnInvalidLValueAssignment(IToken token)
101-
=> new(FormatForSchema(ASIN01, "Invalid l-value for assignment", token));
109+
internal static ScriptRuntimeException FailOnInvalidLValueAssignment(string code, IToken token)
110+
=> new(FormatForSchema(code, "Invalid l-value for assignment (readonly)", token));
102111

103112
internal static ScriptInvocationException FailOnTargetNotFound(IToken token)
104113
=> new(TRGT01, "Target not found for function '~%0'", token);
105114

106115
internal static ScriptInvocationException FailOnCallerNotFound(IToken token)
107116
=> new(CALR01, "Caller not found for function '~%0'", token);
108117

109-
internal static ScriptRuntimeException FailOnIdentifierNotFound(IToken identifier)
110-
=> new(FormatForSchema(VARD02, $"Identifier '{identifier.Text}' not found", identifier));
118+
internal static ScriptRuntimeException FailOnIdentifierNotFound(string code, IToken identifier)
119+
=> new(FormatForSchema(code, $"Identifier '{identifier.Text}' not found", identifier));
111120

112-
internal static ScriptRuntimeException FailOnFunctionNotFound(string name, int arity,
121+
internal static ScriptRuntimeException FailOnFunctionNotFound(string name, int argCount,
113122
IToken token)
114-
=> new(FormatForSchema(FUNS04, $"Function '{name}' with {arity} parameter(s) not found",
123+
=> new(FormatForSchema(FNVK01, $"Function '{name}' with {argCount} parameter(s) not found",
115124
token));
116125

117126
internal static ScriptRuntimeException FailOnRuntime(string code, string message, IToken token,
118127
Exception innerException)
119128
=> new(FormatForSchema(code, message, token), innerException);
120129

121-
internal static ScriptInvocationException FailOnVariadicArgument(string code)
130+
internal static ScriptInvocationException FailOnVariadicArity(string code)
122131
=> new(code, "Too few arguments for invocation of variadic function '~%0'");
123132

124-
internal static ScriptInvocationException FailOnFixedArgument(string code)
133+
internal static ScriptInvocationException FailOnFixedArity(string code)
125134
=> new(code, "Invalid number of arguments for function '~%0'");
126135

127136
internal static SystemOperationException FailOnSystemException(string code,
128137
Exception exception, IToken token)
129138
=> new(FormatForSchema(code, exception.Message, token), exception);
130139

131-
internal static ScriptOperationException FailOnOperation(string code, string operationName,
140+
internal static ScriptOperationException FailOnOperation(string code, string operation,
132141
IEValue value, IToken token, Exception? innerException = null)
133-
=> new(FormatForSchema(code, $"Invalid {operationName} operation on type {
142+
=> new(FormatForSchema(code, $"Invalid {operation} operation on type {
134143
value.Type}", token), innerException);
135144

136-
internal static ScriptRuntimeException FailOnOperation(string code, string operationName,
145+
internal static ScriptRuntimeException FailOnOperation(string code, string operation,
137146
IEValue value, ITerminalNode node)
138-
=> FailOnOperation(code, operationName, value, node.Symbol);
147+
=> FailOnOperation(code, operation, value, node.Symbol);
139148

140-
internal static ScriptOperationException FailOnOperation(string code, string operationName,
149+
internal static ScriptOperationException FailOnOperation(string code, string operation,
141150
IEValue value1, IEValue value2, IToken token, Exception? innerException = null)
142-
=> new(FormatForSchema(code, $"Invalid {operationName} operation on types {
151+
=> new(FormatForSchema(code, $"Invalid {operation} operation on types {
143152
value1.Type} and {value2.Type}", token), innerException);
144153

145-
internal static ScriptRuntimeException FailOnOperation(string code, string operationName,
154+
internal static ScriptRuntimeException FailOnOperation(string code, string operation,
146155
IEValue value1, IEValue value2, ITerminalNode node)
147-
=> FailOnOperation(code, operationName, value1, value2, node.Symbol);
156+
=> FailOnOperation(code, operation, value1, value2, node.Symbol);
157+
158+
internal static ScriptRuntimeException FailOnStringUpdate(string code, ITerminalNode node)
159+
=> new(FormatForSchema(code, "Immutable string characters cannot be updated", node.Symbol));
160+
161+
internal static ScriptRuntimeException FailOnArrayRangeUpdate(string code, ITerminalNode node)
162+
=> new(FormatForSchema(code, "Update a range of elements in array is not supported",
163+
node.Symbol));
148164
}

JSchema/RelogicLabs/JSchema/Engine/ScriptContext.cs renamed to JSchema/RelogicLabs/JSchema/Engine/ScriptGlobalScope.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22

33
namespace RelogicLabs.JSchema.Engine;
44

5-
internal sealed class ScriptContext : ScopeContext
5+
internal sealed class ScriptGlobalScope : ScriptScope
66
{
77
private readonly RuntimeContext _runtime;
88

9-
public ScriptContext(RuntimeContext runtime) : base(null)
9+
public ScriptGlobalScope(RuntimeContext runtime) : base(null)
1010
=> _runtime = runtime;
1111

1212
public override RuntimeContext GetRuntime() => _runtime;

JSchema/RelogicLabs/JSchema/Engine/ScopeContext.cs renamed to JSchema/RelogicLabs/JSchema/Engine/ScriptScope.cs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,22 @@
55
using RelogicLabs.JSchema.Utilities;
66
using static RelogicLabs.JSchema.Library.ScriptLibrary;
77
using static RelogicLabs.JSchema.Message.ErrorCode;
8-
using static RelogicLabs.JSchema.Script.GFunction;
8+
using static RelogicLabs.JSchema.Tree.IEFunction;
99

1010
namespace RelogicLabs.JSchema.Engine;
1111

12-
internal class ScopeContext
12+
internal class ScriptScope
1313
{
14-
public ScopeContext? Parent { get; }
14+
private readonly ScriptScope? _parent;
1515
private readonly Dictionary<string, IEValue> _symbols;
1616

17-
public ScopeContext(ScopeContext? parent)
17+
public ScriptScope(ScriptScope? parent)
1818
{
19-
Parent = parent;
19+
_parent = parent;
2020
_symbols = new Dictionary<string, IEValue>();
2121
}
2222

23-
public GReference AddVariable(string name, IEValue value)
23+
public virtual GReference AddVariable(string name, IEValue value)
2424
{
2525
var reference = new GReference(value);
2626
var result = _symbols.TryAdd(name, reference);
@@ -34,30 +34,30 @@ public void AddFunction(string name, GFunction function)
3434
var result = _symbols.TryAdd(name, function);
3535
if(result) return;
3636
if(name.StartsWith(ConstraintPrefix))
37-
throw FailOnDuplicateDefinition(FUNS02, "Constraint", name);
38-
throw FailOnDuplicateDefinition(FUNS03, "Subroutine", name);
37+
throw FailOnDuplicateDefinition(FUND01, "Constraint", name);
38+
throw FailOnDuplicateDefinition(FUND02, "Subroutine", name);
3939
}
4040

4141
private static ScriptFunctionException FailOnDuplicateDefinition(string code,
4242
string functionType, string name) => new(code, $"{functionType} function '{
4343
name.SubstringBefore('#')}' with matching parameter(s) already defined");
4444

45-
public IEValue Resolve(string name)
45+
public IEValue? Resolve(string name)
4646
{
4747
var current = this;
4848
do
4949
{
5050
current._symbols.TryGetValue(name, out var value);
5151
if(value != null) return value;
52-
current = current.Parent;
52+
current = current._parent;
5353
} while(current != null);
5454
return ResolveStatic(name);
5555
}
5656

5757
public virtual RuntimeContext GetRuntime()
5858
{
5959
var current = this;
60-
while(current.Parent != null) current = current.Parent;
60+
while(current._parent != null) current = current._parent;
6161
return current.GetRuntime();
6262
}
6363

JSchema/RelogicLabs/JSchema/Engine/ScriptTreeHelper.cs

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
using RelogicLabs.JSchema.Tree;
55
using RelogicLabs.JSchema.Types;
66
using static RelogicLabs.JSchema.Engine.ScriptErrorHelper;
7-
using static RelogicLabs.JSchema.Script.IRFunction;
87
using static RelogicLabs.JSchema.Script.GFunction;
98
using static RelogicLabs.JSchema.Utilities.CommonUtilities;
109

@@ -55,15 +54,15 @@ public static void AreCompatible(IRFunction function, List<IEValue> arguments, s
5554
var paramCount = function.Parameters.Length;
5655
if(function.Variadic)
5756
{
58-
if(arguments.Count < paramCount - 1) throw FailOnVariadicArgument(code);
57+
if(arguments.Count < paramCount - 1) throw FailOnVariadicArity(code);
5958
return;
6059
}
61-
if(arguments.Count != paramCount) throw FailOnFixedArgument(code);
60+
if(arguments.Count != paramCount) throw FailOnFixedArity(code);
6261
}
6362

6463
public static string Stringify(object value)
6564
=> value is IEString s ? s.Value : value.ToString()
66-
?? throw new InvalidOperationException("Invalid runtime state");
65+
?? throw new InvalidOperationException("Invalid runtime state");
6766

6867
public static int GetFunctionMode(ITerminalNode constraint, ITerminalNode future,
6968
ITerminalNode subroutine) => GetFunctionMode(constraint)
@@ -75,18 +74,14 @@ private static int GetFunctionMode(ITerminalNode? node)
7574
if(node == null) return 0;
7675
return node.Symbol.Type switch
7776
{
78-
SchemaLexer.G_CONSTRAINT => ConstraintMode,
79-
SchemaLexer.G_FUTURE => FutureMode,
80-
SchemaLexer.G_SUBROUTINE => SubroutineMode,
77+
SchemaParser.G_CONSTRAINT => ConstraintMode,
78+
SchemaParser.G_FUTURE => FutureMode,
79+
SchemaParser.G_SUBROUTINE => SubroutineMode,
8180
_ => 0
8281
};
8382
}
8483

8584
public static bool IsConstraint(int mode) => HasFlag(mode, ConstraintMode);
86-
public static string ToConstraintName(string functionName) => ConstraintPrefix + functionName;
87-
88-
public static string FormatFunctionName(string baseName, GParameter[] parameters)
89-
=> HasVariadic(parameters) ? baseName + "#..." : baseName + "#" + parameters.Length;
9085

9186
public static GParameter[] ToParameters(IList<ITerminalNode> identifiers, ITerminalNode? ellipsis)
9287
{
@@ -100,16 +95,16 @@ public static GParameter[] ToParameters(IList<ITerminalNode> identifiers, ITermi
10095
}
10196

10297
public static IENumber Increment(IENumber number)
103-
=> number is IEInteger i ? GInteger.Of(i.Value + 1) : GDouble.Of(number.ToDouble() + 1);
98+
=> number is IEInteger i ? GInteger.From(i.Value + 1) : GDouble.From(number.ToDouble() + 1);
10499

105100
public static IENumber Decrement(IENumber number)
106-
=> number is IEInteger i ? GInteger.Of(i.Value - 1) : GDouble.Of(number.ToDouble() - 1);
101+
=> number is IEInteger i ? GInteger.From(i.Value - 1) : GDouble.From(number.ToDouble() - 1);
107102

108103
public static GObject CreateTryofMonad(IEValue value, IEValue error)
109104
{
110105
var result = new GObject(2);
111-
result.Set(TryofValue, value);
112-
result.Set(TryofError, error);
106+
result.Put(TryofValue, value);
107+
result.Put(TryofError, error);
113108
return result;
114109
}
115110

0 commit comments

Comments
 (0)