String squeak(smalltallk)如何将字符串“注入”到字符串中

String squeak(smalltallk)如何将字符串“注入”到字符串中,string,smalltalk,squeak,String,Smalltalk,Squeak,我正在写一个名为MyObject的类。 类方法之一是: addTo: aCodeString assertType: aTypeCollection 当使用aCodeString调用该方法时,我想在运行时向MyObject类添加一个新方法,aCodeString是它的源代码,并将类型检查代码注入源代码。 例如,如果我调用addTo:assertType:like: a := MyObject new. a addTo: 'foo: a boo:b baz: c ^(a*b+c)' a

我正在写一个名为MyObject的类。 类方法之一是:

addTo: aCodeString assertType: aTypeCollection
当使用aCodeString调用该方法时,我想在运行时向MyObject类添加一个新方法,aCodeString是它的源代码,并将类型检查代码注入源代码。 例如,如果我调用addTo:assertType:like:

a := MyObject new.
a addTo:  'foo: a boo:b baz: c
    ^(a*b+c)'
assertType: #(SmallInteger SmallInteger SmallInteger).
我希望我可以稍后再写:

answer := (a foo: 2 boo: 5 baz: 10). 
答案是20。 如果我写:

a foo: 'someString' boo: 5 baz: 10.
我得到了正确的消息,因为“someString”不是一个小整数

我知道如何编写类型检查代码,并且我知道要在运行时将该方法添加到类中,我可以使用行为类中的“compile”方法

问题是我想在源代码中添加类型检查代码。 我不是很熟悉所有的squeak类,所以我不确定我是否愿意在addTo:assertType:内将aCodeString作为字符串编辑,然后使用compile:并且我不知道如何这样做,或者是否有一种方法可以将代码注入行为类或其他squeak类中的现有方法


所以基本上,我要问的是如何将字符串注入现有字符串或将代码注入现有方法。

有很多方法可以实现这种类型检查

您建议的方法是将源代码修改为字符串,以便插入附加的前置条件类型检查

这种方法的关键点是必须在正确的位置插入类型检查。这意味着以某种方式解析原始源或至少是选择器和参数,以便找到其确切范围和参数名称

请参阅解析器及其发送者中的initPattern:return:方法。你会发现相当低级但不是最漂亮的代码,它通过return:keyword和sap提供了一个由3个对象组成的数组:方法选择器、方法参数和方法优先级。一个代码告诉你方法是否连接到一元、二进制或关键字消息。从那里,您将获得足够的材料来实现源代码操作,并使用copyReplace:From:to:with:将字符串插入到另一个字符串中

请毫不犹豫地编写小代码片段并在调试器中执行选择要调试的代码,然后使用debug it菜单或ALT+Shift+D。还可以广泛使用检查器,以获得有关如何工作的更多信息

另一个解决方案是解析源代码的整个抽象语法树AST,并操纵该AST以插入类型检查。通常,解析器构建AST,因此请观察它的工作方式。从修改后的AST中,您可以生成新的CompiledMethod字节码指令,并将其安装在methodDictionary中-请参阅compile:的源代码,然后按照发送的消息进行操作,直到发现generateMethodFromNode:trailer:。这有点复杂,并且有一个坏的副作用,即源代码现在与生成的代码不同步,这可能会在您想要调试该方法时成为一个问题幸运的是,Squeak可以使用反编译代码代替源代码

最后,您还可以为某些类安排一个备用编译器和解析器,请参见compilerClass和/或parserClass。替代的TypeHintParser将接受源代码中带有类型提示的修改语法很久以前,它是通过尖括号foo:x bar:y中的args后面的类型提示实现的。备用类型hintCompiler将根据这些类型提示自动编译前置条件。因为您将在Squeak方面非常先进,所以您还将在源代码索引和字节码之间创建特殊映射,以便拥有sane调试器,甚至可以识别前置条件类型检查并将其转换回类型提示的特殊反编译器类,以防万一

我的建议是从你提议的第一种方法开始

编辑


我忘了说,还有另一种方法,但它目前在Pharo而不是Squeak中可用:名为OpalCompiler的Pharo编译器在生成阶段将字节码指令具体化为以IR开头的对象类名称。因此,在这个阶段,通过适当的黑客攻击也可以直接操作字节码指令。。。我很确定我们可以找到使用的例子。可能是最先进的技术。

虽然向方法中注入代码很有趣,但我不认为通过大量工作来获得基于类的类型检查会带来任何好处。这与所有的Smalltalk实践背道而驰,因为它阻碍了多态性应用。请不要忘记接受您的答案。如果它没有回答你的问题,请在你的问题或答案下面发表评论。