解离出Runner
This commit is contained in:
26
DoRunner/BackpointRunner.cs
Normal file
26
DoRunner/BackpointRunner.cs
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
using Convention.RScript.Parser;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
|
||||||
|
namespace Convention.RScript.Runner
|
||||||
|
{
|
||||||
|
public class BackpointRunner : JumpRuntimePointerRunner
|
||||||
|
{
|
||||||
|
[return: MaybeNull]
|
||||||
|
public override object Run(ExpressionParser parser, RScriptSentence sentence, RScriptContext context)
|
||||||
|
{
|
||||||
|
// 检查并跳转到上次跳转的位置
|
||||||
|
if (parser.Evaluate<bool>(sentence.content))
|
||||||
|
{
|
||||||
|
if (context.GotoPointerStack.Count == 0)
|
||||||
|
{
|
||||||
|
throw new RScriptRuntimeException($"No position to back.", context.CurrentRuntimePointer);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DoJumpRuntimePointer(parser, context.GotoPointerStack.Pop(), context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
32
DoRunner/BreakpointRunner.cs
Normal file
32
DoRunner/BreakpointRunner.cs
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
using Convention.RScript.Parser;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
|
||||||
|
namespace Convention.RScript
|
||||||
|
{
|
||||||
|
public class BreakpointRunner : IRSentenceRunner
|
||||||
|
{
|
||||||
|
[return: MaybeNull]
|
||||||
|
public object Run(ExpressionParser parser, RScriptSentence sentence, RScriptContext context)
|
||||||
|
{
|
||||||
|
// 检查并跳转到当前命名空间的结束位置
|
||||||
|
if (parser.Evaluate<bool>(sentence.content))
|
||||||
|
{
|
||||||
|
if (context.RuntimePointerStack.Count == 0)
|
||||||
|
{
|
||||||
|
context.CurrentRuntimePointer = context.Sentences.Length;
|
||||||
|
}
|
||||||
|
else if (context.NamespaceLayer.TryGetValue(context.RuntimePointerStack.Peek(), out var exitPointer))
|
||||||
|
{
|
||||||
|
context.CurrentRuntimePointer = exitPointer;
|
||||||
|
//DoExitNamespace(parser);
|
||||||
|
context.SentenceRunners[RScriptSentence.Mode.ExitNamespace].Run(parser, context.CurrentSentence, context);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new RScriptRuntimeException($"No namespace to break.", context.CurrentRuntimePointer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
67
DoRunner/DefineVariableRunner.cs
Normal file
67
DoRunner/DefineVariableRunner.cs
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
using Convention.RScript.Parser;
|
||||||
|
using System;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
|
||||||
|
namespace Convention.RScript.Runner
|
||||||
|
{
|
||||||
|
public class DefineVariableRunner : IRSentenceRunner
|
||||||
|
{
|
||||||
|
[return: MaybeNull]
|
||||||
|
public object Run(ExpressionParser parser, RScriptSentence sentence, RScriptContext context)
|
||||||
|
{
|
||||||
|
// 定义变量
|
||||||
|
var varTypeName = sentence.info[0];
|
||||||
|
var varName = sentence.info[1];
|
||||||
|
var varInitExpression = sentence.info[2];
|
||||||
|
Type varType;
|
||||||
|
object varDefaultValue;
|
||||||
|
{
|
||||||
|
if (varTypeName == "string")
|
||||||
|
{
|
||||||
|
varType = typeof(string);
|
||||||
|
varDefaultValue = varInitExpression == null ? string.Empty : varInitExpression;
|
||||||
|
}
|
||||||
|
else if (varTypeName == "int")
|
||||||
|
{
|
||||||
|
varType = typeof(int);
|
||||||
|
varDefaultValue = varInitExpression == null ? 0 : parser.Evaluate<int>(varInitExpression);
|
||||||
|
}
|
||||||
|
else if (varTypeName == "double")
|
||||||
|
{
|
||||||
|
varType = typeof(double);
|
||||||
|
varDefaultValue = varInitExpression == null ? 0.0 : parser.Evaluate<double>(varInitExpression);
|
||||||
|
}
|
||||||
|
else if (varTypeName == "float")
|
||||||
|
{
|
||||||
|
varType = typeof(float);
|
||||||
|
varDefaultValue = varInitExpression == null ? 0.0f : parser.Evaluate<float>(varInitExpression);
|
||||||
|
}
|
||||||
|
else if (varTypeName == "bool")
|
||||||
|
{
|
||||||
|
varType = typeof(bool);
|
||||||
|
varDefaultValue = varInitExpression == null ? false : parser.Evaluate<bool>(varInitExpression);
|
||||||
|
}
|
||||||
|
else if (varTypeName == "var")
|
||||||
|
{
|
||||||
|
varType = typeof(object);
|
||||||
|
varDefaultValue = varInitExpression == null ? new object() : parser.Evaluate(varInitExpression);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new RScriptRuntimeException($"Unsupported variable type '{varTypeName}'.", context.CurrentRuntimePointer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (context.CurrentLocalSpaceVariableNames.Peek().Contains(varName) == false)
|
||||||
|
{
|
||||||
|
context.Variables.Add(varName, new(varType, varDefaultValue));
|
||||||
|
parser.context.Variables[varName] = varDefaultValue;
|
||||||
|
context.CurrentLocalSpaceVariableNames.Peek().Add(varName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new RScriptRuntimeException($"Variable '{varName}' already defined on this namespace.", context.CurrentRuntimePointer);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
23
DoRunner/EnterNamespaceRunner.cs
Normal file
23
DoRunner/EnterNamespaceRunner.cs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
using Convention.RScript.Parser;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
|
||||||
|
namespace Convention.RScript.Runner
|
||||||
|
{
|
||||||
|
public class EnterNamespaceRunner : IRSentenceRunner
|
||||||
|
{
|
||||||
|
[return: MaybeNull]
|
||||||
|
public object Run(ExpressionParser parser, RScriptSentence sentence, RScriptContext context)
|
||||||
|
{
|
||||||
|
// 准备记录当前命名空间中定义的变量, 清空上层命名空间的变量
|
||||||
|
context.CurrentLocalSpaceVariableNames.Push(new());
|
||||||
|
// 更新变量值
|
||||||
|
foreach (var (varName, varValue) in parser.context.Variables)
|
||||||
|
{
|
||||||
|
context.Variables.SetValue(varName, varValue);
|
||||||
|
}
|
||||||
|
// 压栈
|
||||||
|
context.RuntimePointerStack.Push(context.CurrentRuntimePointer);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
28
DoRunner/ExitNamespaceRunner.cs
Normal file
28
DoRunner/ExitNamespaceRunner.cs
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
using Convention.RScript.Parser;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
|
||||||
|
namespace Convention.RScript.Runner
|
||||||
|
{
|
||||||
|
public class ExitNamespaceRunner : IRSentenceRunner
|
||||||
|
{
|
||||||
|
[return: MaybeNull]
|
||||||
|
public object Run(ExpressionParser parser, RScriptSentence sentence, RScriptContext context)
|
||||||
|
{
|
||||||
|
// 移除当前命名空间的变量
|
||||||
|
foreach (var local in context.CurrentLocalSpaceVariableNames.Peek())
|
||||||
|
{
|
||||||
|
context.Variables.Remove(local);
|
||||||
|
parser.context.Variables.Remove(local);
|
||||||
|
}
|
||||||
|
// 还原上层命名空间的变量
|
||||||
|
foreach (var local in context.CurrentLocalSpaceVariableNames.Peek())
|
||||||
|
{
|
||||||
|
parser.context.Variables[local] = context.Variables[local].data;
|
||||||
|
}
|
||||||
|
context.CurrentLocalSpaceVariableNames.Pop();
|
||||||
|
// 弹栈
|
||||||
|
context.RuntimePointerStack.Pop();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
14
DoRunner/ExpressionRunner.cs
Normal file
14
DoRunner/ExpressionRunner.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
using Convention.RScript.Parser;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
|
||||||
|
namespace Convention.RScript.Runner
|
||||||
|
{
|
||||||
|
public class ExpressionRunner : IRSentenceRunner
|
||||||
|
{
|
||||||
|
[return: MaybeNull]
|
||||||
|
public object Run(ExpressionParser parser, RScriptSentence sentence, RScriptContext context)
|
||||||
|
{
|
||||||
|
return parser.Evaluate(sentence.content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
47
DoRunner/GoToRunner.cs
Normal file
47
DoRunner/GoToRunner.cs
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
using Convention.RScript.Parser;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
|
||||||
|
namespace Convention.RScript.Runner
|
||||||
|
{
|
||||||
|
public class GoToRunner : JumpRuntimePointerRunner
|
||||||
|
{
|
||||||
|
[return: MaybeNull]
|
||||||
|
public override object Run(ExpressionParser parser, RScriptSentence sentence, RScriptContext context)
|
||||||
|
{
|
||||||
|
// 检查并跳转到指定标签
|
||||||
|
if (parser.Evaluate<bool>(sentence.info[0]))
|
||||||
|
{
|
||||||
|
if (context.Labels.TryGetValue(sentence.content, out var labelPointer))
|
||||||
|
{
|
||||||
|
context.GotoPointerStack.Push(context.CurrentRuntimePointer);
|
||||||
|
DoJumpRuntimePointer(parser, labelPointer, context);
|
||||||
|
}
|
||||||
|
else if (context.NamespaceLabels.TryGetValue(sentence.content, out labelPointer))
|
||||||
|
{
|
||||||
|
int current = context.CurrentRuntimePointer;
|
||||||
|
//DoEnterNamespace(parser);
|
||||||
|
context.SentenceRunners[RScriptSentence.Mode.EnterNamespace].Run(parser, context.CurrentSentence, context);
|
||||||
|
context.CurrentRuntimePointer = labelPointer;
|
||||||
|
for (int e = context.NamespaceLayer[context.NamespaceLabels[sentence.content]]; ;)
|
||||||
|
{
|
||||||
|
context.RunNextStep(parser);
|
||||||
|
if (context.CurrentRuntimePointer >= context.Sentences.Length)
|
||||||
|
break;
|
||||||
|
else if (context.CurrentRuntimePointer == e)
|
||||||
|
break;
|
||||||
|
else
|
||||||
|
context.CurrentRuntimePointer++;
|
||||||
|
}
|
||||||
|
//context.DoExitNamespace(parser);
|
||||||
|
context.SentenceRunners[RScriptSentence.Mode.ExitNamespace].Run(parser, context.CurrentSentence, context);
|
||||||
|
context.CurrentRuntimePointer = current;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new RScriptRuntimeException($"Label '{sentence.content}' not found.", context.CurrentRuntimePointer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
38
DoRunner/JumpRuntimePointerRunner.cs
Normal file
38
DoRunner/JumpRuntimePointerRunner.cs
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
using Convention.RScript.Parser;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
|
||||||
|
namespace Convention.RScript.Runner
|
||||||
|
{
|
||||||
|
public abstract class JumpRuntimePointerRunner : IRSentenceRunner
|
||||||
|
{
|
||||||
|
protected void DoJumpRuntimePointer(ExpressionParser parser, int target, RScriptContext context)
|
||||||
|
{
|
||||||
|
bool isForwardMove = target > context.CurrentRuntimePointer;
|
||||||
|
int step = isForwardMove ? 1 : -1;
|
||||||
|
for (; context.CurrentRuntimePointer != target; context.CurrentRuntimePointer += step)
|
||||||
|
{
|
||||||
|
if (context.CurrentSentence.mode == RScriptSentence.Mode.ExitNamespace)
|
||||||
|
{
|
||||||
|
if (isForwardMove)
|
||||||
|
//DoExitNamespace(parser);
|
||||||
|
context.SentenceRunners[RScriptSentence.Mode.ExitNamespace].Run(parser, context.CurrentSentence, context);
|
||||||
|
else
|
||||||
|
//DoEnterNamespace(parser);
|
||||||
|
context.SentenceRunners[RScriptSentence.Mode.EnterNamespace].Run(parser, context.CurrentSentence, context);
|
||||||
|
}
|
||||||
|
else if (context.CurrentSentence.mode == RScriptSentence.Mode.EnterNamespace)
|
||||||
|
{
|
||||||
|
if (isForwardMove)
|
||||||
|
//DoEnterNamespace(parser);
|
||||||
|
context.SentenceRunners[RScriptSentence.Mode.EnterNamespace].Run(parser, context.CurrentSentence, context);
|
||||||
|
else
|
||||||
|
//DoExitNamespace(parser);
|
||||||
|
context.SentenceRunners[RScriptSentence.Mode.ExitNamespace].Run(parser, context.CurrentSentence, context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[return: MaybeNull]
|
||||||
|
public abstract object Run(ExpressionParser parser, RScriptSentence sentence, RScriptContext context);
|
||||||
|
}
|
||||||
|
}
|
@@ -1,8 +1,10 @@
|
|||||||
using Convention.RScript.Matcher;
|
using Convention.RScript.Matcher;
|
||||||
using Convention.RScript.Parser;
|
using Convention.RScript.Parser;
|
||||||
|
using Convention.RScript.Runner;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace Convention.RScript
|
namespace Convention.RScript
|
||||||
@@ -69,14 +71,19 @@ namespace Convention.RScript
|
|||||||
bool Match(string expression, ref RScriptSentence sentence);
|
bool Match(string expression, ref RScriptSentence sentence);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface IRSentenceRunner
|
||||||
|
{
|
||||||
|
[return: MaybeNull] object Run(ExpressionParser parser, RScriptSentence sentence, RScriptContext context);
|
||||||
|
}
|
||||||
|
|
||||||
public partial class RScriptContext
|
public partial class RScriptContext
|
||||||
{
|
{
|
||||||
public readonly RScriptImportClass Import;
|
public readonly RScriptImportClass Import;
|
||||||
public readonly RScriptVariables Variables;
|
public readonly RScriptVariables Variables;
|
||||||
private readonly RScriptSentence[] Sentences;
|
internal readonly RScriptSentence[] Sentences;
|
||||||
private readonly Dictionary<string, int> Labels = new();
|
internal readonly Dictionary<string, int> Labels = new();
|
||||||
private readonly Dictionary<int, int> NamespaceLayer = new();
|
internal readonly Dictionary<int, int> NamespaceLayer = new();
|
||||||
private readonly Dictionary<string, int> NamespaceLabels = new();
|
internal readonly Dictionary<string, int> NamespaceLabels = new();
|
||||||
|
|
||||||
public List<IRSentenceMatcher> SentenceParser = new()
|
public List<IRSentenceMatcher> SentenceParser = new()
|
||||||
{
|
{
|
||||||
@@ -161,241 +168,24 @@ namespace Convention.RScript
|
|||||||
|
|
||||||
public RScriptSentence CurrentSentence => Sentences[CurrentRuntimePointer];
|
public RScriptSentence CurrentSentence => Sentences[CurrentRuntimePointer];
|
||||||
|
|
||||||
private void DoDefineVariable(ExpressionParser parser, RScriptSentence sentence)
|
public Dictionary<RScriptSentence.Mode, IRSentenceRunner> SentenceRunners = new()
|
||||||
{
|
{
|
||||||
// 定义变量
|
{ RScriptSentence.Mode.DefineVariable, new DefineVariableRunner() },
|
||||||
var varTypeName = sentence.info[0];
|
{ RScriptSentence.Mode.EnterNamespace, new EnterNamespaceRunner() },
|
||||||
var varName = sentence.info[1];
|
{ RScriptSentence.Mode.ExitNamespace, new ExitNamespaceRunner() },
|
||||||
var varInitExpression = sentence.info[2];
|
{ RScriptSentence.Mode.Goto, new GoToRunner() },
|
||||||
Type varType;
|
{ RScriptSentence.Mode.Breakpoint, new BreakpointRunner() },
|
||||||
object varDefaultValue;
|
{ RScriptSentence.Mode.Backpoint, new BackpointRunner() },
|
||||||
{
|
{ RScriptSentence.Mode.Expression, new ExpressionRunner() },
|
||||||
if (varTypeName == "string")
|
};
|
||||||
{
|
|
||||||
varType = typeof(string);
|
|
||||||
varDefaultValue = varInitExpression == null ? string.Empty : varInitExpression;
|
|
||||||
}
|
|
||||||
else if (varTypeName == "int")
|
|
||||||
{
|
|
||||||
varType = typeof(int);
|
|
||||||
varDefaultValue = varInitExpression == null ? 0 : parser.Evaluate<int>(varInitExpression);
|
|
||||||
}
|
|
||||||
else if (varTypeName == "double")
|
|
||||||
{
|
|
||||||
varType = typeof(double);
|
|
||||||
varDefaultValue = varInitExpression == null ? 0.0 : parser.Evaluate<double>(varInitExpression);
|
|
||||||
}
|
|
||||||
else if (varTypeName == "float")
|
|
||||||
{
|
|
||||||
varType = typeof(float);
|
|
||||||
varDefaultValue = varInitExpression == null ? 0.0f : parser.Evaluate<float>(varInitExpression);
|
|
||||||
}
|
|
||||||
else if (varTypeName == "bool")
|
|
||||||
{
|
|
||||||
varType = typeof(bool);
|
|
||||||
varDefaultValue = varInitExpression == null ? false : parser.Evaluate<bool>(varInitExpression);
|
|
||||||
}
|
|
||||||
else if (varTypeName == "var")
|
|
||||||
{
|
|
||||||
varType = typeof(object);
|
|
||||||
varDefaultValue = varInitExpression == null ? new object() : parser.Evaluate(varInitExpression);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new RScriptRuntimeException($"Unsupported variable type '{varTypeName}'.", CurrentRuntimePointer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (CurrentLocalSpaceVariableNames.Peek().Contains(varName) == false)
|
|
||||||
{
|
|
||||||
Variables.Add(varName, new(varType, varDefaultValue));
|
|
||||||
parser.context.Variables[varName] = varDefaultValue;
|
|
||||||
CurrentLocalSpaceVariableNames.Peek().Add(varName);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new RScriptRuntimeException($"Variable '{varName}' already defined on this namespace.", CurrentRuntimePointer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DoEnterNamespace(ExpressionParser parser)
|
|
||||||
{
|
|
||||||
// 准备记录当前命名空间中定义的变量, 清空上层命名空间的变量
|
|
||||||
CurrentLocalSpaceVariableNames.Push(new());
|
|
||||||
// 更新变量值
|
|
||||||
foreach (var (varName, varValue) in parser.context.Variables)
|
|
||||||
{
|
|
||||||
Variables.SetValue(varName, varValue);
|
|
||||||
}
|
|
||||||
// 压栈
|
|
||||||
RuntimePointerStack.Push(CurrentRuntimePointer);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DoExitNamespace(ExpressionParser parser)
|
internal object RunNextStep(ExpressionParser parser)
|
||||||
{
|
|
||||||
// 移除当前命名空间的变量
|
|
||||||
foreach (var local in CurrentLocalSpaceVariableNames.Peek())
|
|
||||||
{
|
|
||||||
Variables.Remove(local);
|
|
||||||
parser.context.Variables.Remove(local);
|
|
||||||
}
|
|
||||||
// 还原上层命名空间的变量
|
|
||||||
foreach (var local in CurrentLocalSpaceVariableNames.Peek())
|
|
||||||
{
|
|
||||||
parser.context.Variables[local] = Variables[local].data;
|
|
||||||
}
|
|
||||||
CurrentLocalSpaceVariableNames.Pop();
|
|
||||||
// 弹栈
|
|
||||||
RuntimePointerStack.Pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DoJumpRuntimePointer(ExpressionParser parser, int target)
|
|
||||||
{
|
|
||||||
bool isForwardMove = target > CurrentRuntimePointer;
|
|
||||||
int step = isForwardMove ? 1 : -1;
|
|
||||||
for (; CurrentRuntimePointer != target; CurrentRuntimePointer += step)
|
|
||||||
{
|
|
||||||
if (CurrentSentence.mode == RScriptSentence.Mode.ExitNamespace)
|
|
||||||
{
|
|
||||||
if (isForwardMove)
|
|
||||||
DoExitNamespace(parser);
|
|
||||||
else
|
|
||||||
DoEnterNamespace(parser);
|
|
||||||
}
|
|
||||||
else if (CurrentSentence.mode == RScriptSentence.Mode.EnterNamespace)
|
|
||||||
{
|
|
||||||
if (isForwardMove)
|
|
||||||
DoEnterNamespace(parser);
|
|
||||||
else
|
|
||||||
DoExitNamespace(parser);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DoGoto(ExpressionParser parser, RScriptSentence sentence)
|
|
||||||
{
|
|
||||||
// 检查并跳转到指定标签
|
|
||||||
if (parser.Evaluate<bool>(sentence.info[0]))
|
|
||||||
{
|
|
||||||
if (Labels.TryGetValue(sentence.content, out var labelPointer))
|
|
||||||
{
|
|
||||||
GotoPointerStack.Push(CurrentRuntimePointer);
|
|
||||||
DoJumpRuntimePointer(parser, labelPointer);
|
|
||||||
}
|
|
||||||
else if (NamespaceLabels.TryGetValue(sentence.content, out labelPointer))
|
|
||||||
{
|
|
||||||
int current = CurrentRuntimePointer;
|
|
||||||
DoEnterNamespace(parser);
|
|
||||||
CurrentRuntimePointer = labelPointer;
|
|
||||||
for (int e = NamespaceLayer[NamespaceLabels[sentence.content]]; ;)
|
|
||||||
{
|
|
||||||
RunNextStep(parser);
|
|
||||||
if (CurrentRuntimePointer >= Sentences.Length)
|
|
||||||
break ;
|
|
||||||
else if (CurrentRuntimePointer == e)
|
|
||||||
break;
|
|
||||||
else
|
|
||||||
CurrentRuntimePointer++;
|
|
||||||
}
|
|
||||||
DoExitNamespace(parser);
|
|
||||||
CurrentRuntimePointer = current;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new RScriptRuntimeException($"Label '{sentence.content}' not found.", CurrentRuntimePointer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DoBreakpoint(ExpressionParser parser, RScriptSentence sentence)
|
|
||||||
{
|
|
||||||
// 检查并跳转到当前命名空间的结束位置
|
|
||||||
if (parser.Evaluate<bool>(sentence.content))
|
|
||||||
{
|
|
||||||
if (RuntimePointerStack.Count == 0)
|
|
||||||
{
|
|
||||||
CurrentRuntimePointer = Sentences.Length;
|
|
||||||
}
|
|
||||||
else if (NamespaceLayer.TryGetValue(RuntimePointerStack.Peek(), out var exitPointer))
|
|
||||||
{
|
|
||||||
CurrentRuntimePointer = exitPointer;
|
|
||||||
DoExitNamespace(parser);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new RScriptRuntimeException($"No namespace to break.", CurrentRuntimePointer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DoBackpoint(ExpressionParser parser, RScriptSentence sentence)
|
|
||||||
{
|
|
||||||
// 检查并跳转到上次跳转的位置
|
|
||||||
if (parser.Evaluate<bool>(sentence.content))
|
|
||||||
{
|
|
||||||
if (GotoPointerStack.Count == 0)
|
|
||||||
{
|
|
||||||
throw new RScriptRuntimeException($"No position to back.", CurrentRuntimePointer);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DoJumpRuntimePointer(parser, GotoPointerStack.Pop());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DoEnterNamedSpace(RScriptSentence sentence)
|
|
||||||
{
|
|
||||||
CurrentRuntimePointer = NamespaceLayer[NamespaceLabels[sentence.content]];
|
|
||||||
}
|
|
||||||
|
|
||||||
private object RunNextStep(ExpressionParser parser)
|
|
||||||
{
|
{
|
||||||
var sentence = CurrentSentence;
|
var sentence = CurrentSentence;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
switch (sentence.mode)
|
return SentenceRunners.TryGetValue(sentence.mode, out var runner) ? runner.Run(parser, sentence, this) : null;
|
||||||
{
|
|
||||||
case RScriptSentence.Mode.Expression:
|
|
||||||
return parser.Evaluate(sentence.content);
|
|
||||||
case RScriptSentence.Mode.DefineVariable:
|
|
||||||
{
|
|
||||||
DoDefineVariable(parser, sentence);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case RScriptSentence.Mode.EnterNamespace:
|
|
||||||
{
|
|
||||||
DoEnterNamespace(parser);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case RScriptSentence.Mode.ExitNamespace:
|
|
||||||
{
|
|
||||||
DoExitNamespace(parser);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case RScriptSentence.Mode.Goto:
|
|
||||||
{
|
|
||||||
DoGoto(parser, sentence);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case RScriptSentence.Mode.Breakpoint:
|
|
||||||
{
|
|
||||||
DoBreakpoint(parser, sentence);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case RScriptSentence.Mode.Backpoint:
|
|
||||||
{
|
|
||||||
DoBackpoint(parser, sentence);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case RScriptSentence.Mode.NamedSpace:
|
|
||||||
{
|
|
||||||
DoEnterNamedSpace(sentence);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// Do nothing
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (RScriptRuntimeException)
|
catch (RScriptRuntimeException)
|
||||||
{
|
{
|
||||||
@@ -405,13 +195,12 @@ namespace Convention.RScript
|
|||||||
{
|
{
|
||||||
throw new RScriptRuntimeException($"Runtime error: {ex.Message}", CurrentRuntimePointer, ex);
|
throw new RScriptRuntimeException($"Runtime error: {ex.Message}", CurrentRuntimePointer, ex);
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly Stack<int> RuntimePointerStack = new();
|
internal readonly Stack<int> RuntimePointerStack = new();
|
||||||
private readonly Stack<int> GotoPointerStack = new();
|
internal readonly Stack<int> GotoPointerStack = new();
|
||||||
private int CurrentRuntimePointer = 0;
|
public int CurrentRuntimePointer { get; internal set; } = 0;
|
||||||
private readonly Stack<HashSet<string>> CurrentLocalSpaceVariableNames = new();
|
internal readonly Stack<HashSet<string>> CurrentLocalSpaceVariableNames = new();
|
||||||
|
|
||||||
public Dictionary<string, RScriptVariableEntry> GetCurrentVariables()
|
public Dictionary<string, RScriptVariableEntry> GetCurrentVariables()
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user