Skip to content

Commit 5788ef5

Browse files
committed
Split the Hypervisor's RunImpl method into parts for each instruction (within reason)
Allows for advanced overriding of script behavior at execution time, as these split instruction methods are overridable and the Hypervisor constructor is now protected instead of private (allowing inheritance).
1 parent aa7c53c commit 5788ef5

File tree

7 files changed

+402
-368
lines changed

7 files changed

+402
-368
lines changed
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
using System.Text;
2+
using Starscript.Internal;
3+
4+
namespace Starscript;
5+
6+
// ReSharper disable VirtualMemberNeverOverridden.Global
7+
// ReSharper disable once ClassWithVirtualMembersNeverInherited.Global
8+
public partial class StarscriptHypervisor
9+
{
10+
protected virtual void Append(ref StringBuilder sb) => AppendValue(sb, Pop());
11+
12+
protected virtual void ConstantAppend(ref StringBuilder sb, ref ExecutableScript script, ref int insnPtr)
13+
=> AppendValue(sb, script.Constants[script.GetMasked(insnPtr++)]);
14+
15+
protected virtual void VariableAppend(ref StringBuilder sb, ref ExecutableScript script, ref int insnPtr)
16+
{
17+
var name = script.Constants[script.GetMasked(insnPtr++)].GetString();
18+
19+
AppendValue(sb, GetVariable(name));
20+
}
21+
22+
protected virtual void GetAppend(ref StringBuilder sb, ref ExecutableScript script, ref int insnPtr)
23+
{
24+
var name = script.Constants[script.GetMasked(insnPtr++)].GetString();
25+
26+
var value = Pop();
27+
28+
AppendValue(sb, value.IsMap
29+
? value.GetMap().GetRaw(name)?.Invoke()
30+
: null);
31+
}
32+
33+
protected virtual void CallAppend(ref StringBuilder sb, ref ExecutableScript script, ref int insnPtr)
34+
{
35+
var argCount = script[insnPtr++];
36+
37+
var a = Peek(argCount);
38+
39+
if (a.IsNull)
40+
throw Error("Unknown function.");
41+
42+
if (!a.IsFunction)
43+
throw Error("Tried to call {0}, can only call functions.", Enum.GetName(a.Type));
44+
45+
var result = a.GetFunction()(this, argCount);
46+
Pop();
47+
AppendValue(sb, result);
48+
}
49+
50+
protected virtual void VariableGetAppend(ref StringBuilder sb, ref ExecutableScript script, ref int insnPtr)
51+
{
52+
Value? value;
53+
54+
{
55+
// Variable
56+
var name = script.Constants[script.GetMasked(insnPtr++)].GetString();
57+
value = GetVariable(name) ?? Value.Null;
58+
}
59+
60+
{
61+
// Get
62+
var name = script.Constants[script.GetMasked(insnPtr++)].GetString();
63+
64+
if (!value.IsMap)
65+
{
66+
Push(null);
67+
return;
68+
}
69+
70+
value = value.GetMap().GetRaw(name)?.Invoke();
71+
}
72+
73+
AppendValue(sb, value);
74+
}
75+
}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
namespace Starscript;
2+
3+
// ReSharper disable VirtualMemberNeverOverridden.Global
4+
// ReSharper disable once ClassWithVirtualMembersNeverInherited.Global
5+
public partial class StarscriptHypervisor
6+
{
7+
protected virtual void Add()
8+
{
9+
var (a, b) = PopPair();
10+
11+
if (a.IsNumber && b.IsNumber)
12+
Push(a.GetNumber() + b.GetNumber());
13+
else if (a.IsString)
14+
Push(a.GetString() + b);
15+
else
16+
throw Error("Can only add 2 numbers, or 1 string and any other value.");
17+
}
18+
19+
protected virtual void Negate()
20+
{
21+
var a = Pop();
22+
23+
if (!a.IsNumber)
24+
throw Error("Negation requires a number.");
25+
26+
Push(-a.GetNumber());
27+
}
28+
29+
protected virtual void Subtract()
30+
{
31+
var (a, b) = PopPair();
32+
33+
if (a.IsNumber && b.IsNumber)
34+
Push(a.GetNumber() - b.GetNumber());
35+
else
36+
throw Error("Can only subtract 2 numbers.");
37+
}
38+
39+
protected virtual void Multiply()
40+
{
41+
var (a, b) = PopPair();
42+
43+
if (a.IsNumber && b.IsNumber)
44+
Push(a.GetNumber() * b.GetNumber());
45+
else
46+
throw Error("Can only multiply 2 numbers.");
47+
}
48+
49+
protected virtual void Divide()
50+
{
51+
var (a, b) = PopPair();
52+
53+
if (a.IsNumber && b.IsNumber)
54+
Push(a.GetNumber() / b.GetNumber());
55+
else
56+
throw Error("Can only divide 2 numbers.");
57+
}
58+
59+
protected virtual void Modulo()
60+
{
61+
var (a, b) = PopPair();
62+
63+
if (a.IsNumber && b.IsNumber)
64+
Push(a.GetNumber() % b.GetNumber());
65+
else
66+
throw Error("Can only modulo 2 numbers.");
67+
}
68+
69+
protected virtual void Power()
70+
{
71+
var (a, b) = PopPair();
72+
73+
if (a.IsNumber && b.IsNumber)
74+
Push(Math.Pow(a.GetNumber(), b.GetNumber()));
75+
else
76+
throw Error("Can only power 2 numbers.");
77+
}
78+
79+
protected virtual void RightShift()
80+
{
81+
var (a, b) = PopPair();
82+
83+
if (a.IsNumber && b.IsNumber)
84+
Push(Convert.ToInt32(a.GetNumber()) >> Convert.ToInt32(double.Truncate(b.GetNumber())));
85+
else
86+
throw Error(">> operation requires 2 numbers.");
87+
}
88+
89+
protected virtual void LeftShift()
90+
{
91+
var (a, b) = PopPair();
92+
93+
if (a.IsNumber && b.IsNumber)
94+
Push(Convert.ToInt32(a.GetNumber()) << Convert.ToInt32(double.Truncate(b.GetNumber())));
95+
else
96+
throw Error("<< operation requires 2 numbers.");
97+
}
98+
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
using Starscript.Internal;
2+
3+
namespace Starscript;
4+
5+
// ReSharper disable VirtualMemberNeverOverridden.Global
6+
// ReSharper disable once ClassWithVirtualMembersNeverInherited.Global
7+
public partial class StarscriptHypervisor
8+
{
9+
protected virtual void Jump(ref ExecutableScript script, ref int insnPtr)
10+
{
11+
var jump = (script.GetMasked(insnPtr++) << 8)
12+
| script.GetMasked(insnPtr++);
13+
14+
insnPtr += jump;
15+
}
16+
17+
protected virtual void JumpIfTrue(ref ExecutableScript script, ref int insnPtr)
18+
{
19+
var jump = (script.GetMasked(insnPtr++) << 8)
20+
| script.GetMasked(insnPtr++);
21+
22+
if (Peek().IsTruthy)
23+
insnPtr += jump;
24+
}
25+
26+
protected virtual void JumpIfFalse(ref ExecutableScript script, ref int insnPtr)
27+
{
28+
var jump = (script.GetMasked(insnPtr++) << 8)
29+
| script.GetMasked(insnPtr++);
30+
31+
if (!Peek().IsTruthy)
32+
insnPtr += jump;
33+
}
34+
35+
protected virtual void Not() => Push(!Pop().IsTruthy);
36+
37+
protected virtual void Equals()
38+
{
39+
// ReSharper disable once EqualExpressionComparison
40+
Push(Pop().Equals(Pop()));
41+
}
42+
43+
protected virtual void NotEquals()
44+
{
45+
// ReSharper disable once EqualExpressionComparison
46+
Push(!Pop().Equals(Pop()));
47+
}
48+
49+
protected virtual void Greater()
50+
{
51+
var (a, b) = PopPair();
52+
53+
if (a.IsNumber && b.IsNumber)
54+
Push(a.GetNumber() > b.GetNumber());
55+
else
56+
throw Error("> operation requires 2 numbers.");
57+
}
58+
59+
protected virtual void GreaterEqual()
60+
{
61+
var (a, b) = PopPair();
62+
63+
if (a.IsNumber && b.IsNumber)
64+
Push(a.GetNumber() >= b.GetNumber());
65+
else
66+
throw Error(">= operation requires 2 numbers.");
67+
}
68+
69+
protected virtual void Less()
70+
{
71+
var (a, b) = PopPair();
72+
73+
if (a.IsNumber && b.IsNumber)
74+
Push(a.GetNumber() < b.GetNumber());
75+
else
76+
throw Error("< operation requires 2 numbers.");
77+
}
78+
79+
protected virtual void LessEqual()
80+
{
81+
var (a, b) = PopPair();
82+
83+
if (a.IsNumber && b.IsNumber)
84+
Push(a.GetNumber() <= b.GetNumber());
85+
else
86+
throw Error("<= operation requires 2 numbers.");
87+
}
88+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
using Starscript.Internal;
2+
3+
namespace Starscript;
4+
5+
// ReSharper disable VirtualMemberNeverOverridden.Global
6+
// ReSharper disable once ClassWithVirtualMembersNeverInherited.Global
7+
public partial class StarscriptHypervisor
8+
{
9+
protected virtual void AddConstant(ref ExecutableScript script, ref int insnPtr)
10+
{
11+
var b = script.Constants[script.GetMasked(insnPtr++)];
12+
var a = Pop();
13+
14+
if (a.IsNumber && b.IsNumber)
15+
Push(a.GetNumber() + b.GetNumber());
16+
else if (a.IsString)
17+
Push(a.GetString() + b);
18+
else
19+
throw Error("Can only add 2 numbers, or 1 string and any other value.");
20+
}
21+
22+
private void Constant(ref ExecutableScript script, ref int insnPtr)
23+
=> Push(script.Constants[script.GetMasked(insnPtr++)]);
24+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
using Starscript.Internal;
2+
3+
namespace Starscript;
4+
5+
// ReSharper disable VirtualMemberNeverOverridden.Global
6+
// ReSharper disable once ClassWithVirtualMembersNeverInherited.Global
7+
public partial class StarscriptHypervisor
8+
{
9+
protected virtual void Variable(ref ExecutableScript script, ref int insnPtr)
10+
{
11+
var name = script.Constants[script.GetMasked(insnPtr++)].GetString();
12+
13+
Push(GetVariable(name));
14+
}
15+
16+
protected virtual void Get(ref ExecutableScript script, ref int insnPtr)
17+
{
18+
var name = script.Constants[script.GetMasked(insnPtr++)].GetString();
19+
20+
var value = Pop();
21+
22+
Push(!value.IsMap
23+
? Value.Null
24+
: GetVariable(name)
25+
);
26+
}
27+
28+
protected virtual void VariableGet(ref ExecutableScript script, ref int insnPtr)
29+
{
30+
Value value;
31+
32+
{
33+
// Variable
34+
var name = script.Constants[script.GetMasked(insnPtr++)].GetString();
35+
value = GetVariable(name) ?? Value.Null;
36+
}
37+
38+
{
39+
// Get
40+
var name = script.Constants[script.GetMasked(insnPtr++)].GetString();
41+
42+
Push(value.IsMap
43+
? value.GetMap().GetRaw(name)?.Invoke()
44+
: null
45+
);
46+
}
47+
}
48+
49+
protected virtual void Call(ref ExecutableScript script, ref int insnPtr)
50+
{
51+
var argCount = script[insnPtr++];
52+
53+
var a = Peek(argCount);
54+
55+
if (a.IsNull)
56+
throw Error("Unknown function.");
57+
58+
if (!a.IsFunction)
59+
throw Error("Tried to call {0}, can only call functions.", Enum.GetName(a.Type));
60+
61+
var result = a.GetFunction()(this, argCount);
62+
Pop();
63+
Push(result);
64+
}
65+
}

0 commit comments

Comments
 (0)