解离出Runner

This commit is contained in:
2025-10-16 15:20:53 +08:00
parent e2ab2a1077
commit 15bdb6f8db
9 changed files with 301 additions and 237 deletions

View 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;
}
}
}

View 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;
}
}
}

View 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;
}
}
}

View 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;
}
}
}

View 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;
}
}
}

View 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
View 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;
}
}
}

View 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);
}
}