> On 08 Sep 2015, at 03:02, Sean P. DeNigris <[hidden email]> wrote: > > From Günter Khyo: > > Günter Khyo wrote >> Hello! >> >> I want to replace particular nodes of an AST (such as Assignments or Self >> sends) with my own nodes. >> Is there an easy (high-level) way to do this without being familiar with >> the entire compiler infrastructure? >> >> The problem I am having is that AST nodes maintain internal state such as >> parent links and, in the case of RBVariables, links to scopes and >> bindings. There might be many other dependencies I am missing and missing >> one of them can trigger exceptions with stack traces buried deep in the IR >> Code-Generator and visitor calls. >> >> For example, if I want to replace an assignment such as >> >> Morph>>position: aPoint >> >> "box := self fullBounds." >> >> with something like >> >> "self assignAndNotifiyDependents: self fullBounds to: 'box' " >> >> Btw: I know there is a rewrite tool, but I want to do it programmatically. Hello, With Pharo5 there are two mechanism that can help you. 1) MetaLinks (aka reflectivity). ======================= They allow you to reflectively define that a meta object to be called before/after or instead of an AST node. as you want to do something in addition here, you can add the notification as a #before link: link := MetaLink new metaObject: #object; selector: #assignAndNotifiyDependents:; arguments: #(newValue). this is a link that when installed on an AssignmentNode, will call #assignAndNotifiyDependents on the object with the new value (the to be assigned value) as the argument. To install this on all ivar assignments, do: MyClass assignmentNodes do: [ :each | each variable isInstance ifTrue: [each link: link ]]. to get rid of the link: link uninstall But MetaLinks are very hidden: you do not see them in your design. So they should be used with care. 2) First class Instance variable (aka Slots). ================================= In your example, what you really want is a “special” kind of variable that always notifies depends. Wouldn’t it be nice if you could define such a special kind of Variable and, in the class definition of you class, specify that the ivar ‘box” is that special kind? In Pharo5, you can do just that. 1) define your special variable. IndexedSlot subclass: #NotifyDependsSlot slots: { } classVariables: { } category: 'Demo’ change what it means to write these kind of variables by implementing: write: aValue to: anObject super write: aValue to: anObject. anObject assignAndNotifiyDependents: aValue. Now change the class definition of your class to make ‘box’ into this special kind of variable: Object subclass: #MyClass slots: { #box => NotifyDependsSlot } classVariables: { } category: ‘Demo' DONE. Ah, but reflective slot write is slow, so if you use this a lot, add these two method: emitValue: methodBuilder methodBuilder pushInstVar: index. emitStore: methodBuilder | tempName | tempName := Object new. methodBuilder addTemp: tempName; storeTemp: tempName; pushReceiver; pushTemp: tempName; send: #assignAndNotifiyDependents:; popTop; storeInstVar: index. These generate byte code inline for the read and write instead of calling the #write:to: method. (I attach a fillout of MyClass that i used to test this) MyClass.st (778 bytes) Download Attachment |
Free forum by Nabble | Edit this page |