我正在使现有的 .Net 应用程序可以为非编程用户编写脚本。我添加了lua,它就像一个魅力。然后我添加了debug functionality(pause/continue/step)通过debug.sethook。它也像一个魅力。
现在我意识到我的应用程序需要像 Visual Studio 那样的编辑和继续功能。您暂停执行可以编辑代码,然后从当前状态继续应用更改。这个功能对我来说非常重要。我认为这对于脚本语言来说很容易做到。
我到处都读到脚本语言可以做到这一点。但即使花了几个小时的搜索,我还没有找到 Lua 实现。它不一定是 Lua,但 Lua 中的热交换代码将是我的第一选择。
如何为用户提供暂停和编辑脚本的能力,然后在应用更改后继续执行?
注意:不一定是 Lua,每种脚本语言都可以
更新
@Schollii 这是一个例子:
function doOnX()
if getValue() == "200" then
value = getCalculation()
doSomething() -- many function calls, each can take about 2s
doSomething()
doSomething()
print(value)
doX(value)
end
end
doOnX()
感谢您的建议。它可能是这样工作的:
- 我将使用https://github.com/frabert/NetLua它是一个非常酷、写得很好的 100% C# Lua 解释器。它首先生成一个 AST 树,然后直接执行它。
- 需要修改解析器。在 Parser.cs
public Ast.Block ParseString(string Chunk)
中,首先生成一个 parseTree。 parseTree.tokens[i].locations 包含每个标记的确切位置。然后,Irony.Parsing.ParseTree
再次被解析并转换为NetLua.Ast.Block
,但位置信息丢失。我需要更改它,以便稍后我知道哪个语句位于哪一行。 - 现在 AST 树中的每个语句都通过 EvalBlock 直接执行。需要添加调试功能(就像我在 C Binding lua Interpreter DynamicLua 中通过 debug.setHook 那样)。这可以在 LuaInterpreter.cs 内部 static LuaArguments EvalBlock(` 中完成。暂停/继续/步骤函数应该没问题。我现在还可以添加当前行突出显示,因为每个语句都包含位置行信息。
- 当执行暂停并编辑代码时,当前的 LuaContxct 将被保存。它包含所有变量。最后一条执行行的最后一条语句也会被保存。
- 现在代码字符串再次被解析为新的 AST 树。它被执行。但所有语句都会被跳过,直到到达带有 line 语句的已保存语句。已保存的
LuaContext
将恢复,并且可以在应用所有更改后继续执行。
新变量也可以在最后执行的行之后添加,因为新的 NetLua.Ast.Assignment 语句可以将新变量添加到当前的 LuaContext 中,并且一切都应该正常工作。
这行得通吗?
最佳答案
我认为正确地做到这一点非常具有挑战性和棘手。
可能唯一的方法就是完全重新编译该代码块。在函数中,这意味着整个函数,无论编辑在函数中的哪个位置。然后再次调用该函数。显然,该函数必须是可重入的,否则它的副作用(例如增加全局值或上值)将必须被撤消,这是不可能的。如果它不可重入,它仍然可以工作,只是不会给出预期的结果(例如,如果函数将全局变量增加 1,再次调用它会导致函数最终返回时全局变量增加 2)。
但是,如果是真正通用的解决方案,那么在脚本中找到 chunkn 开始和结束的行将会很棘手。对于特定的解决方案,您必须发布要运行的脚本的具体示例以及要编辑的行的示例。如果整个用户脚本被重新编译并重新运行,那么这不是问题,但副作用仍然是一个问题,示例也可以提供帮助。
关于支持 "edit and continue"或 "hot swap"的脚本语言? (也许在 Lua 中可能吗?),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26191664/