SlideShare a Scribd company logo
1 of 52
Download to read offline
Advanced Reflection:
MetaLinks
Marcus Denker, Inria
http://marcusdenker.de
Lecture at VUB Brussels, October 30, 2019
What we know…
• Smalltalk is reflective

• Classes, Methods, Stack-Frames… are Objects

• Reflective API on all Objects
Take home message
• Reflection is based on the meta-class model, thus
inherently structural.
• Behavioural reflection limited to:
• Method lookup upon failure ( doesNotUnderstand:
message)
• Current execution reified (thisContext)
61
Can we do better?
• A more fine-grained reflective mechanism seems to be
missing

• Let’s look again at a Method in the Inspector
Inspector on a Method
The AST
• AST = Abstract Syntax Tree

• Tree Representation of the Method

• Produced by the Parser (part of the Compiler)

• Used by all tools (refactoring, syntax-highlighting,…)
Smalltalk compiler parse: 'test ^(1+2)'
AST
• RBMethodNode Root

• RBVariableNode Variable (read and write)

• RBAssignmentNode Assignment

• RBMessageNode A Message (most of them)

• RBReturnNode Return
Inspect a simple AST
• A very simple Example
Smalltalk compiler parse: 'test ^(1+2)'
AST: Navigation
• To make it easy to find and enumerate nodes, there are
some helper methods

• CompiledMethod has: #sendNodes,
#variableNodes, #assignmentNodes
• Every AST node has #nodesDo: and #allChildren
AST: Visitor
• RBProgramNodeVisitor: Visitor Pattern for the AST

• Make subclass, override visit… methods

• Let’s see it in action: Count Message sends
Demo: Visitor
Repeat:The AST
• AST = Abstract Syntax Tree

• Tree Representation of the Method

• Produced by the Parser (part of the Compiler)

• Used by all tools (refactoring, syntax-highlighting,…)
Smalltalk compiler parse: 'test ^(1+2)'
The Compiler
• Smalltalk compiler -> Compiler Facade 

• Classes define the compiler to use

• You can override method #compiler

• Behind: Compiler Chain
The Compiler
Source AST
Annotated
AST
IR
Annotated
AST
Bytecode
RBParser OCSemanticAnalyzer
OCASTTranslator/
IRBuilder
IRBytecodeGenerator
AST Integration
• Originally just internal to the compiler

• Pharo: 

• send #ast to a method to get the AST

• Cached for persistency.
(Point>>#x) ast == (Point>>#x) ast
—> true
AST Integration
• We can navigate from execution to AST

• Example:
[ 1 + 2 ] sourceNode ==
thisContext method sourceNode blockNodes first
Compiler: Extensible
• All parts can be subclassed

• Compiler instance can be setup to use the subclass for
any part (parser, name analysis, translator…)

• enable for a class only by implementing #compiler on the
class side
Compiler Plugins
• The AST can be easily transformed

• We added a Plugin architecture to the Compiler

• enable for a class only by implementing:
compiler

	 ^super compiler addPlugin: MyPlugin
The Compiler
Source AST
Annotated
AST
IR
Annotated
AST
Bytecode
RBParser OCSemanticAnalyzer
OCASTTranslator/
IRBuilder
IRBytecodeGenerator
Plugin
Source AST
Annotated
AST
IR
Annotated
AST
Bytecode
RBParser OCSemanticAnalyzer
OCASTTranslator/
IRBuilder
IRBytecodeGenerator
OCCompilerASTPlugin
Annotated
AST
Plugin: Example
• We get all ifTrue: sends

• replace them with true
DemoPlugin>>transform
transform
| sends |
sends := ast sendNodes.
sends := sends select: [ :each | each selector = #ifTrue: ].
sends do: [:each | each replaceWith:
(RBLiteralNode value: true)].
^ast
Back to the topic…
• A more fine-grained reflective mechanism seems to be
missing

• Can’t we do something with the AST?
Wouldn’t it be nice..
• With the AST, wouldn’t it be nice if we could use this
structure for Behavioural Reflection?

• If we could somehow attach a “arrow to the code” that
points to a meta-object
test
^( 1 + 2 )
meta-object
for this Send
We have all pieces…
• We have the AST for each method

• It is quite simple

• We have a compiler in the system

• So this should be possible…
The MetaLink
• MetaLink points to metaObject

• Defines a selector to call

• And a control attribute: #before, #after, #instead

• Installed on a AST node:
link := MetaLink new
metaObject: Halt;
selector: #once;
control: #before.
(Number>>#sin) ast link: link
The MetaLink
• Can be installed on any AST Node

• Methods will be re-compiled on the fly just before next
execution

• Link installation is very fast

• Changing a method removes all links from this method

• Managing link re-installation has to be done by the user
MetaLink: MetaObject
• MetaObject can be any object

• Even a Block: [Transcript show ‘hello’]
• Install on any Node with #link:

• de-install a link with #uninstall
MetaLink: Selector
• MetaLink defines a message send to the MetaObject

• #selector defines which one

• Default is #value

• Yes, a selector with arguments is supported 

• We can pass information to the meta-object
MetaLink: Argument
• The arguments define which arguments to pass

• We support a number of reifications
Reifications
• Reifications define data to be passed as arguments

• Reify —> Make something into an object that is not one
normally

• Example: “All arguments of this message”
Reifications: examples
• All nodes: #object #context #class #node
#link
• Sends: #arguments #receiver #selector
• Method: #arguments #selector 

• Variable: #value

They are defined as subclasses of class RFReification
Reifications as MetaObject
• We support some special metaObjects:

• #node The AST Node we are installed on

• #object self at runtime

• #class The class the links is installed in
MetaLink: Condition
• We can specify a condition for the MetaLink

• Link is active if the condition evaluates to true
• We can pass reifications as arguments
link := MetaLink new
metaObject: Halt;
selector: #once;
condition: [:object | object == 5] arguments: #(object).
(Number>>#sin) ast link: link.
MetaLink: control
• We can specify when to call the meta-object

• We support #before, #after and #instead
• The instead is very simple: last one wins
Example: Log
• We want to just print something to the Transcript
link := MetaLink new
metaObject: [Transcript show: 'Reached Here'].
(Number>>#sin) ast link: link
Recursion Problem
• Before we see more examples: There is a problem

• Imagine we put a MetaLink on some method deep in the
System (e.g new, +, do: ).

• Our Meta-Object might use exactly that method, too
Endless Loop!!
Recursion Problem
• Solution: Meta-Level

• We encode the a level in the execution of the system

• Every Link Activation increases the level

• A meta-link is just active for one level. (e.g. 0)
link := MetaLink new
metaObject: [ Object new ];
level: 0.
(Behavior>>#new) ast link: link.
Example: Log
• Better use #level: 0

• Nevertheless: be careful! If you add this to method called
often it can be very slow.
link := MetaLink new
metaObject: [Transcript show: 'Reached Here’];
level: 0.
Example: Counter
• In the Browser you can add a “counter” to the AST

• See class ExecutionCounter
install
link := MetaLink new
metaObject: self;
selector: #increase.
node link: link.
Example: Breakpoint
• “Add Breakpoint” in AST (Suggestions) Menu

• See class Breakpoint

• Break Once 

• Conditional Break breakLink
^ MetaLink new
metaObject: Break;
selector: #break;
options: options
Example: WatchPoint
• Watchpoint: Record Value at a point in the AST

• Example: Watch event in WorldMorph>>#mouseDown:
Click on background
-> value recorded
Example: WatchPoint
• Implementation: class Watchpoint, method install

• example of a #after link with a condition
link := MetaLink new
metaObject: self;
selector: #addValue:;
arguments: #(value);
control: #after;
condition: [ recording ].
Example: Code Coverage
• Small Demo.

• Start with CoverageDemo new openWithSpec
Example: Code Coverage
• Example of a MetaLink with a #node MetaObject

• Meta-Object is the node that the link is installed on
link := MetaLink new
metaObject: #node;
selector: #tagExecuted.
Interesting Properties
• Cross Cutting

• One Link can be installed multiple times

• Over multiple methods and even Classes

• And across operations (e.g., Send and Assignment) as
long as all reifications requested are compatible

• Fully Dynamic: Links can be added and removed at runtime

• Even by the meta-object of another meta-link!
Example: Accept for Test
• Imagine we want to edit a method that is called often by
the System.

• How do we test it?

• It would be nice if we could “Accept for Test”
Example: Accept for Test
• Menu in the browser. Quick hack, a Suggestions AST
menu shows for all nodes.
SugsSuggestion subclass: #SugsAcceptForTest
instanceVariableNames: ''
classVariableNames: ''
package: 'SmartSuggestions-Suggestion'
label
^'Accept for test'
• We implement our code in the #execute method
Example: Accept for Test
• How we know that we are in a test?
CurrentExecutionEnvironment value isTest
• We can compile the current text buffer
newMethod := context selectedClass compiler
source: context code;
options: #(+ optionParseErrors);
compile.
Example: Accept for Test
• Add this code to the beginning of the method:
[:aContext :args |
CurrentExecutionEnvironment value isTest ifTrue: [
aContext return: (newMethod
valueWithReceiver: aContext
receiver
arguments: args) ]]
• Let’s do that with a MetaLink!
Example: Accept for Test
execute
| newMethod metaLink |
newMethod := context selectedClass compiler
source: context code;
options: #(+ optionParseErrors);
compile.
"the link executes the method we just created and returns"
metaLink := MetaLink new
metaObject: [ :aContext :args |
CurrentExecutionEnvironment value isTest
ifTrue: [ aContext return: (newMethod
valueWithReceiver: aContext receiver
arguments: args) ] ];
selector: #value:value:;
arguments: #(context arguments).
context selectedMethod ast link: metaLink
Limitations
• #instead needs more work (e.g to support conditions)

• Keep in mind: next metaLink taken into account for next
method activation 

• Take care with long running loops!
Help Wanted
• We are always interested in improvements!

• Pharo 8 is under active development. 

• Pull Requests Welcome!

More Related Content

What's hot

Whoops! where did my architecture go?
Whoops! where did my architecture go?Whoops! where did my architecture go?
Whoops! where did my architecture go?
Oliver Gierke
 
Async in .NET
Async in .NETAsync in .NET
Async in .NET
RTigger
 

What's hot (20)

Variables in Pharo5
Variables in Pharo5Variables in Pharo5
Variables in Pharo5
 
Enhanced Web Service Testing: A Better Mock Structure
Enhanced Web Service Testing: A Better Mock StructureEnhanced Web Service Testing: A Better Mock Structure
Enhanced Web Service Testing: A Better Mock Structure
 
Enhanced Web Service Testing: A Better Mock Structure
Enhanced Web Service Testing: A Better Mock StructureEnhanced Web Service Testing: A Better Mock Structure
Enhanced Web Service Testing: A Better Mock Structure
 
Whoops! where did my architecture go?
Whoops! where did my architecture go?Whoops! where did my architecture go?
Whoops! where did my architecture go?
 
Whoops! Where did my architecture go?
Whoops! Where did my architecture go?Whoops! Where did my architecture go?
Whoops! Where did my architecture go?
 
Java 8 concurrency abstractions
Java 8 concurrency abstractionsJava 8 concurrency abstractions
Java 8 concurrency abstractions
 
Testing in Scala. Adform Research
Testing in Scala. Adform ResearchTesting in Scala. Adform Research
Testing in Scala. Adform Research
 
The dark side of Akka and the remedy
The dark side of Akka and the remedyThe dark side of Akka and the remedy
The dark side of Akka and the remedy
 
Async in .NET
Async in .NETAsync in .NET
Async in .NET
 
The dark side of Akka and the remedy - bp.scala meetup
The dark side of Akka and the remedy - bp.scala meetupThe dark side of Akka and the remedy - bp.scala meetup
The dark side of Akka and the remedy - bp.scala meetup
 
2014-02-20 | Akka Concurrency (Vienna Scala User Group)
2014-02-20 | Akka Concurrency (Vienna Scala User Group)2014-02-20 | Akka Concurrency (Vienna Scala User Group)
2014-02-20 | Akka Concurrency (Vienna Scala User Group)
 
Legacy Code Kata v3.0
Legacy Code Kata v3.0Legacy Code Kata v3.0
Legacy Code Kata v3.0
 
Reactive Micro Services with Java seminar
Reactive Micro Services with Java seminarReactive Micro Services with Java seminar
Reactive Micro Services with Java seminar
 
Reactive java - Reactive Programming + RxJava
Reactive java - Reactive Programming + RxJavaReactive java - Reactive Programming + RxJava
Reactive java - Reactive Programming + RxJava
 
Async Programming in C# 5
Async Programming in C# 5Async Programming in C# 5
Async Programming in C# 5
 
Legacy Dependency Kata v2.0
Legacy Dependency Kata v2.0Legacy Dependency Kata v2.0
Legacy Dependency Kata v2.0
 
Advanced Reflection in Pharo
Advanced Reflection in PharoAdvanced Reflection in Pharo
Advanced Reflection in Pharo
 
Servlet11
Servlet11Servlet11
Servlet11
 
Streams, Streams Everywhere! An Introduction to Rx
Streams, Streams Everywhere! An Introduction to RxStreams, Streams Everywhere! An Introduction to Rx
Streams, Streams Everywhere! An Introduction to Rx
 
C# 5 deep drive into asynchronous programming
C# 5 deep drive into asynchronous programmingC# 5 deep drive into asynchronous programming
C# 5 deep drive into asynchronous programming
 

Similar to VUB Brussels Lecture 2019: Advanced Reflection: MetaLinks

Presentation 3rd
Presentation 3rdPresentation 3rd
Presentation 3rd
Connex
 
540slidesofnodejsbackendhopeitworkforu.pdf
540slidesofnodejsbackendhopeitworkforu.pdf540slidesofnodejsbackendhopeitworkforu.pdf
540slidesofnodejsbackendhopeitworkforu.pdf
hamzadamani7
 
Akka london scala_user_group
Akka london scala_user_groupAkka london scala_user_group
Akka london scala_user_group
Skills Matter
 
The hardest part of microservices: your data
The hardest part of microservices: your dataThe hardest part of microservices: your data
The hardest part of microservices: your data
Christian Posta
 
Presentation 4th
Presentation 4thPresentation 4th
Presentation 4th
Connex
 

Similar to VUB Brussels Lecture 2019: Advanced Reflection: MetaLinks (20)

Lecture: "Advanced Reflection: MetaLinks"
Lecture: "Advanced Reflection: MetaLinks"Lecture: "Advanced Reflection: MetaLinks"
Lecture: "Advanced Reflection: MetaLinks"
 
Lecture. Advanced Reflection: MetaLinks
Lecture. Advanced Reflection: MetaLinksLecture. Advanced Reflection: MetaLinks
Lecture. Advanced Reflection: MetaLinks
 
Behavioral Reflection in Pharo
Behavioral Reflection in PharoBehavioral Reflection in Pharo
Behavioral Reflection in Pharo
 
#Pharo Days 2016 Reflectivity
#Pharo Days 2016 Reflectivity#Pharo Days 2016 Reflectivity
#Pharo Days 2016 Reflectivity
 
Behavioral Reflection
Behavioral ReflectionBehavioral Reflection
Behavioral Reflection
 
Presentation 3rd
Presentation 3rdPresentation 3rd
Presentation 3rd
 
First Class Variables as AST Annotations
 First Class Variables as AST Annotations First Class Variables as AST Annotations
First Class Variables as AST Annotations
 
First Class Variables as AST Annotations
First Class Variables as AST AnnotationsFirst Class Variables as AST Annotations
First Class Variables as AST Annotations
 
DjangoCon 2010 Scaling Disqus
DjangoCon 2010 Scaling DisqusDjangoCon 2010 Scaling Disqus
DjangoCon 2010 Scaling Disqus
 
Variables in Pharo
Variables in PharoVariables in Pharo
Variables in Pharo
 
540slidesofnodejsbackendhopeitworkforu.pdf
540slidesofnodejsbackendhopeitworkforu.pdf540slidesofnodejsbackendhopeitworkforu.pdf
540slidesofnodejsbackendhopeitworkforu.pdf
 
Data weave (MuleSoft)
Data weave (MuleSoft)Data weave (MuleSoft)
Data weave (MuleSoft)
 
Runtime Bytecode Transformation for Smalltalk
Runtime Bytecode Transformation for SmalltalkRuntime Bytecode Transformation for Smalltalk
Runtime Bytecode Transformation for Smalltalk
 
Akka london scala_user_group
Akka london scala_user_groupAkka london scala_user_group
Akka london scala_user_group
 
The hardest part of microservices: your data
The hardest part of microservices: your dataThe hardest part of microservices: your data
The hardest part of microservices: your data
 
Runtime Bytecode Transformation for Smalltalk
Runtime Bytecode Transformation for SmalltalkRuntime Bytecode Transformation for Smalltalk
Runtime Bytecode Transformation for Smalltalk
 
Unit Testng with PHP Unit - A Step by Step Training
Unit Testng with PHP Unit - A Step by Step TrainingUnit Testng with PHP Unit - A Step by Step Training
Unit Testng with PHP Unit - A Step by Step Training
 
DDD, CQRS and testing with ASP.Net MVC
DDD, CQRS and testing with ASP.Net MVCDDD, CQRS and testing with ASP.Net MVC
DDD, CQRS and testing with ASP.Net MVC
 
Code transformation With Spoon
Code transformation With SpoonCode transformation With Spoon
Code transformation With Spoon
 
Presentation 4th
Presentation 4thPresentation 4th
Presentation 4th
 

More from Marcus Denker

More from Marcus Denker (19)

Soil And Pharo
Soil And PharoSoil And Pharo
Soil And Pharo
 
ConstantBlocks in Pharo11
ConstantBlocks in Pharo11ConstantBlocks in Pharo11
ConstantBlocks in Pharo11
 
Demo: Improved DoIt
Demo: Improved DoItDemo: Improved DoIt
Demo: Improved DoIt
 
Supporting Pharo / Getting Pharo Support
Supporting Pharo / Getting Pharo SupportSupporting Pharo / Getting Pharo Support
Supporting Pharo / Getting Pharo Support
 
thisContext in the Debugger
thisContext in the DebuggerthisContext in the Debugger
thisContext in the Debugger
 
Improving code completion for Pharo
Improving code completion for PharoImproving code completion for Pharo
Improving code completion for Pharo
 
Slot Composition
Slot CompositionSlot Composition
Slot Composition
 
PHARO IOT
PHARO IOTPHARO IOT
PHARO IOT
 
Open-Source: An Infinite Game
Open-Source: An Infinite GameOpen-Source: An Infinite Game
Open-Source: An Infinite Game
 
PharoTechTalk: Contributing to Pharo
PharoTechTalk: Contributing to PharoPharoTechTalk: Contributing to Pharo
PharoTechTalk: Contributing to Pharo
 
Feedback Loops in Practice
Feedback Loops in PracticeFeedback Loops in Practice
Feedback Loops in Practice
 
Pharo6 - ESUG17
Pharo6 - ESUG17Pharo6 - ESUG17
Pharo6 - ESUG17
 
Pharo6
Pharo6Pharo6
Pharo6
 
Perfection & Feedback Loops or: why worse is better
Perfection & Feedback Loops or: why worse is betterPerfection & Feedback Loops or: why worse is better
Perfection & Feedback Loops or: why worse is better
 
How to Contribute to Pharo
How to Contribute to PharoHow to Contribute to Pharo
How to Contribute to Pharo
 
Pharo Status (from PharoDays 2015)
Pharo Status (from PharoDays 2015)Pharo Status (from PharoDays 2015)
Pharo Status (from PharoDays 2015)
 
Pharo Status Fosdem 2015
Pharo Status Fosdem 2015Pharo Status Fosdem 2015
Pharo Status Fosdem 2015
 
Pharo Status ESUG 2014
Pharo Status ESUG 2014Pharo Status ESUG 2014
Pharo Status ESUG 2014
 
Nomads do not build Cathedrals
Nomads do not build CathedralsNomads do not build Cathedrals
Nomads do not build Cathedrals
 

Recently uploaded

Recently uploaded (20)

WSO2Con2024 - Organization Management: The Revolution in B2B CIAM
WSO2Con2024 - Organization Management: The Revolution in B2B CIAMWSO2Con2024 - Organization Management: The Revolution in B2B CIAM
WSO2Con2024 - Organization Management: The Revolution in B2B CIAM
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation Template
 
What Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the SituationWhat Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the Situation
 
WSO2CON 2024 - Not Just Microservices: Rightsize Your Services!
WSO2CON 2024 - Not Just Microservices: Rightsize Your Services!WSO2CON 2024 - Not Just Microservices: Rightsize Your Services!
WSO2CON 2024 - Not Just Microservices: Rightsize Your Services!
 
WSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With SimplicityWSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
 
WSO2CON 2024 - Designing Event-Driven Enterprises: Stories of Transformation
WSO2CON 2024 - Designing Event-Driven Enterprises: Stories of TransformationWSO2CON 2024 - Designing Event-Driven Enterprises: Stories of Transformation
WSO2CON 2024 - Designing Event-Driven Enterprises: Stories of Transformation
 
WSO2Con2024 - Unleashing the Financial Potential of 13 Million People
WSO2Con2024 - Unleashing the Financial Potential of 13 Million PeopleWSO2Con2024 - Unleashing the Financial Potential of 13 Million People
WSO2Con2024 - Unleashing the Financial Potential of 13 Million People
 
WSO2CON 2024 Slides - Unlocking Value with AI
WSO2CON 2024 Slides - Unlocking Value with AIWSO2CON 2024 Slides - Unlocking Value with AI
WSO2CON 2024 Slides - Unlocking Value with AI
 
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
 
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
 
%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto
 
Architecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastArchitecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the past
 
WSO2CON 2024 - How to Run a Security Program
WSO2CON 2024 - How to Run a Security ProgramWSO2CON 2024 - How to Run a Security Program
WSO2CON 2024 - How to Run a Security Program
 
WSO2CON 2024 - Building a Digital Government in Uganda
WSO2CON 2024 - Building a Digital Government in UgandaWSO2CON 2024 - Building a Digital Government in Uganda
WSO2CON 2024 - Building a Digital Government in Uganda
 
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
 
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
 
WSO2Con2024 - Low-Code Integration Tooling
WSO2Con2024 - Low-Code Integration ToolingWSO2Con2024 - Low-Code Integration Tooling
WSO2Con2024 - Low-Code Integration Tooling
 
WSO2CON 2024 - Architecting AI in the Enterprise: APIs and Applications
WSO2CON 2024 - Architecting AI in the Enterprise: APIs and ApplicationsWSO2CON 2024 - Architecting AI in the Enterprise: APIs and Applications
WSO2CON 2024 - Architecting AI in the Enterprise: APIs and Applications
 
WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?
 
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
 

VUB Brussels Lecture 2019: Advanced Reflection: MetaLinks

  • 1. Advanced Reflection: MetaLinks Marcus Denker, Inria http://marcusdenker.de Lecture at VUB Brussels, October 30, 2019
  • 2. What we know… • Smalltalk is reflective • Classes, Methods, Stack-Frames… are Objects • Reflective API on all Objects
  • 3. Take home message • Reflection is based on the meta-class model, thus inherently structural. • Behavioural reflection limited to: • Method lookup upon failure ( doesNotUnderstand: message) • Current execution reified (thisContext) 61
  • 4. Can we do better? • A more fine-grained reflective mechanism seems to be missing • Let’s look again at a Method in the Inspector
  • 5. Inspector on a Method
  • 6. The AST • AST = Abstract Syntax Tree • Tree Representation of the Method • Produced by the Parser (part of the Compiler) • Used by all tools (refactoring, syntax-highlighting,…) Smalltalk compiler parse: 'test ^(1+2)'
  • 7. AST • RBMethodNode Root • RBVariableNode Variable (read and write) • RBAssignmentNode Assignment • RBMessageNode A Message (most of them) • RBReturnNode Return
  • 8. Inspect a simple AST • A very simple Example Smalltalk compiler parse: 'test ^(1+2)'
  • 9. AST: Navigation • To make it easy to find and enumerate nodes, there are some helper methods • CompiledMethod has: #sendNodes, #variableNodes, #assignmentNodes • Every AST node has #nodesDo: and #allChildren
  • 10. AST: Visitor • RBProgramNodeVisitor: Visitor Pattern for the AST • Make subclass, override visit… methods • Let’s see it in action: Count Message sends
  • 12. Repeat:The AST • AST = Abstract Syntax Tree • Tree Representation of the Method • Produced by the Parser (part of the Compiler) • Used by all tools (refactoring, syntax-highlighting,…) Smalltalk compiler parse: 'test ^(1+2)'
  • 13. The Compiler • Smalltalk compiler -> Compiler Facade • Classes define the compiler to use • You can override method #compiler • Behind: Compiler Chain
  • 14. The Compiler Source AST Annotated AST IR Annotated AST Bytecode RBParser OCSemanticAnalyzer OCASTTranslator/ IRBuilder IRBytecodeGenerator
  • 15. AST Integration • Originally just internal to the compiler • Pharo: • send #ast to a method to get the AST • Cached for persistency. (Point>>#x) ast == (Point>>#x) ast —> true
  • 16. AST Integration • We can navigate from execution to AST • Example: [ 1 + 2 ] sourceNode == thisContext method sourceNode blockNodes first
  • 17. Compiler: Extensible • All parts can be subclassed • Compiler instance can be setup to use the subclass for any part (parser, name analysis, translator…) • enable for a class only by implementing #compiler on the class side
  • 18. Compiler Plugins • The AST can be easily transformed • We added a Plugin architecture to the Compiler • enable for a class only by implementing: compiler ^super compiler addPlugin: MyPlugin
  • 19. The Compiler Source AST Annotated AST IR Annotated AST Bytecode RBParser OCSemanticAnalyzer OCASTTranslator/ IRBuilder IRBytecodeGenerator
  • 21. Plugin: Example • We get all ifTrue: sends • replace them with true DemoPlugin>>transform transform | sends | sends := ast sendNodes. sends := sends select: [ :each | each selector = #ifTrue: ]. sends do: [:each | each replaceWith: (RBLiteralNode value: true)]. ^ast
  • 22. Back to the topic… • A more fine-grained reflective mechanism seems to be missing • Can’t we do something with the AST?
  • 23. Wouldn’t it be nice.. • With the AST, wouldn’t it be nice if we could use this structure for Behavioural Reflection? • If we could somehow attach a “arrow to the code” that points to a meta-object test ^( 1 + 2 ) meta-object for this Send
  • 24. We have all pieces… • We have the AST for each method • It is quite simple • We have a compiler in the system • So this should be possible…
  • 25. The MetaLink • MetaLink points to metaObject • Defines a selector to call • And a control attribute: #before, #after, #instead • Installed on a AST node: link := MetaLink new metaObject: Halt; selector: #once; control: #before. (Number>>#sin) ast link: link
  • 26. The MetaLink • Can be installed on any AST Node • Methods will be re-compiled on the fly just before next execution • Link installation is very fast • Changing a method removes all links from this method • Managing link re-installation has to be done by the user
  • 27. MetaLink: MetaObject • MetaObject can be any object • Even a Block: [Transcript show ‘hello’] • Install on any Node with #link: • de-install a link with #uninstall
  • 28. MetaLink: Selector • MetaLink defines a message send to the MetaObject • #selector defines which one • Default is #value • Yes, a selector with arguments is supported • We can pass information to the meta-object
  • 29. MetaLink: Argument • The arguments define which arguments to pass • We support a number of reifications
  • 30. Reifications • Reifications define data to be passed as arguments • Reify —> Make something into an object that is not one normally • Example: “All arguments of this message”
  • 31. Reifications: examples • All nodes: #object #context #class #node #link • Sends: #arguments #receiver #selector • Method: #arguments #selector • Variable: #value
 They are defined as subclasses of class RFReification
  • 32. Reifications as MetaObject • We support some special metaObjects: • #node The AST Node we are installed on • #object self at runtime • #class The class the links is installed in
  • 33. MetaLink: Condition • We can specify a condition for the MetaLink • Link is active if the condition evaluates to true • We can pass reifications as arguments link := MetaLink new metaObject: Halt; selector: #once; condition: [:object | object == 5] arguments: #(object). (Number>>#sin) ast link: link.
  • 34. MetaLink: control • We can specify when to call the meta-object • We support #before, #after and #instead • The instead is very simple: last one wins
  • 35. Example: Log • We want to just print something to the Transcript link := MetaLink new metaObject: [Transcript show: 'Reached Here']. (Number>>#sin) ast link: link
  • 36. Recursion Problem • Before we see more examples: There is a problem • Imagine we put a MetaLink on some method deep in the System (e.g new, +, do: ). • Our Meta-Object might use exactly that method, too Endless Loop!!
  • 37. Recursion Problem • Solution: Meta-Level • We encode the a level in the execution of the system • Every Link Activation increases the level • A meta-link is just active for one level. (e.g. 0) link := MetaLink new metaObject: [ Object new ]; level: 0. (Behavior>>#new) ast link: link.
  • 38. Example: Log • Better use #level: 0 • Nevertheless: be careful! If you add this to method called often it can be very slow. link := MetaLink new metaObject: [Transcript show: 'Reached Here’]; level: 0.
  • 39. Example: Counter • In the Browser you can add a “counter” to the AST • See class ExecutionCounter install link := MetaLink new metaObject: self; selector: #increase. node link: link.
  • 40. Example: Breakpoint • “Add Breakpoint” in AST (Suggestions) Menu • See class Breakpoint • Break Once • Conditional Break breakLink ^ MetaLink new metaObject: Break; selector: #break; options: options
  • 41. Example: WatchPoint • Watchpoint: Record Value at a point in the AST • Example: Watch event in WorldMorph>>#mouseDown: Click on background -> value recorded
  • 42. Example: WatchPoint • Implementation: class Watchpoint, method install • example of a #after link with a condition link := MetaLink new metaObject: self; selector: #addValue:; arguments: #(value); control: #after; condition: [ recording ].
  • 43. Example: Code Coverage • Small Demo. • Start with CoverageDemo new openWithSpec
  • 44. Example: Code Coverage • Example of a MetaLink with a #node MetaObject • Meta-Object is the node that the link is installed on link := MetaLink new metaObject: #node; selector: #tagExecuted.
  • 45. Interesting Properties • Cross Cutting • One Link can be installed multiple times • Over multiple methods and even Classes • And across operations (e.g., Send and Assignment) as long as all reifications requested are compatible • Fully Dynamic: Links can be added and removed at runtime • Even by the meta-object of another meta-link!
  • 46. Example: Accept for Test • Imagine we want to edit a method that is called often by the System. • How do we test it? • It would be nice if we could “Accept for Test”
  • 47. Example: Accept for Test • Menu in the browser. Quick hack, a Suggestions AST menu shows for all nodes. SugsSuggestion subclass: #SugsAcceptForTest instanceVariableNames: '' classVariableNames: '' package: 'SmartSuggestions-Suggestion' label ^'Accept for test' • We implement our code in the #execute method
  • 48. Example: Accept for Test • How we know that we are in a test? CurrentExecutionEnvironment value isTest • We can compile the current text buffer newMethod := context selectedClass compiler source: context code; options: #(+ optionParseErrors); compile.
  • 49. Example: Accept for Test • Add this code to the beginning of the method: [:aContext :args | CurrentExecutionEnvironment value isTest ifTrue: [ aContext return: (newMethod valueWithReceiver: aContext receiver arguments: args) ]] • Let’s do that with a MetaLink!
  • 50. Example: Accept for Test execute | newMethod metaLink | newMethod := context selectedClass compiler source: context code; options: #(+ optionParseErrors); compile. "the link executes the method we just created and returns" metaLink := MetaLink new metaObject: [ :aContext :args | CurrentExecutionEnvironment value isTest ifTrue: [ aContext return: (newMethod valueWithReceiver: aContext receiver arguments: args) ] ]; selector: #value:value:; arguments: #(context arguments). context selectedMethod ast link: metaLink
  • 51. Limitations • #instead needs more work (e.g to support conditions) • Keep in mind: next metaLink taken into account for next method activation • Take care with long running loops!
  • 52. Help Wanted • We are always interested in improvements! • Pharo 8 is under active development. • Pull Requests Welcome!