University of Oviedo Computer Science Department
Francisco OrtinJuan Manuel Cueva
The nitrO Reflective PlatformThe nitrO Reflective Platform
International Conference on International Conference on Software Engineering Research Software Engineering Research
and Practice (SERP)and Practice (SERP)
Session on Adaptable Software Session on Adaptable Software Architectures (ASA)Architectures (ASA)
Francisco OrtinJuan Manuel Cueva
AdaptabilityAdaptability
• Adaptable software systems and architectures give the programmer the ability to create applications that might be customized to runtime-emerging requirements (unpredictable at design time)
• An adaptable platform should give its applications the opportunity to customize their structure and behavior at runtime
Francisco OrtinJuan Manuel Cueva
ReflectionReflection
• Reflection is a programming language technique that achieves dynamic application adaptability
• Taking what system’s feature can be customized as a classification criterion, we can distinguish:
Introspection: Application’s structure might be inspected but not modified (e.g. Java reflect package used in the JavaBeans architecture)
Structural Reflection: Application’s structure might be inspected as well as modified (e.g. Smalltalk and Python ability to modify objects’ structure at runtime)
Computational Reflection: The whole system semantics can be adapted (e.g. modifying the message passing mechanism to create a system’s logger)
Francisco OrtinJuan Manuel Cueva
Meta-Object ProtocolsMeta-Object Protocols
• Most runtime computational-reflective systems are based on Meta-Object Protocols (MOP)
• A MOP specifies the way an application (base level) may access its object-model implementation (meta-level) in order to adapt its behavior and structure at runtime
Interpreter
Runs
User ObjectsUser’sApplication
SemanticsOverriding
Meta-ObjectProtocol
Meta-Object
BaseLevel
Meta-Level
MetaXaExample
MetaObject
attachObject(Object)eventMethodEnter()
System class used to modify the applications semantics
Trace Trace class that overrides the message- passing mechanism
Attaching objects to the meta-object (attachObject) implies behavior adaptation
Francisco OrtinJuan Manuel Cueva
MOP RestrictionsMOP Restrictions
1. The way a MOP is defined restricts the way amount of features that can be customized: if the is not a “create object” meta-object, we will not be able to adapt this system behavior
2. Enhancing the MOP implies different interpreter and language versions Previous code could result deprecated
3. System semantics customization is expressed by method overriding: a richer mechanism to express the adaptation would be needed
4. Meta-level and base-level programming language are the same: the do not offer runtime adaptability in a language-independent way
Francisco OrtinJuan Manuel Cueva
Theoretical ConceptTheoretical Concept
• The theoretical concept of reflection uses the notion of a reflective tower of interpreters:
An interpreter (hardware or software) runs an application
A reflective computation is a computation about its computation: a computation that accesses the interpreter
• If the application would be able to access its interpreter at runtime, it would
Inspect its running objects Introspection Modify its own structure Structural Reflection Customize the language semantics
Computational Reflection
Francisco OrtinJuan Manuel Cueva
System ArchitectureSystem Architecture
• We have developed a Generic Interpreter that: Is capable of interpreting any programming
language by previously reading its specification Separates every language-specific representation
from the interpreter implementation (grammar and semantics)
Separates every application structure from the interpreter implementation (dynamic application’s symbol-table)
Gives the programmer the ability to access every: Application Structure Programming Language Specification
Francisco OrtinJuan Manuel Cueva
System ArchitectureSystem Architecture
GenericInterpreter
Application = “Sample App”Language = “Sample Lang”
Class MyClass {// * App code...
}
User’s Application
1) A user program is about to be run
...
SampleLang.ML
2) The language specification file is found in the system
Language-SpecificationObjects Structure
3) The language specification is translated into a objects structure
4) The user’s application starts running
6) If the application reads its symbol-table, introspection is achieved
7) If the application modifies its symbol-table, structural reflection is achieved
8) If the application modifies the language semantics, computational reflection is achieved
5) While the application is running, a symbol-table is used by the interpreter
Application’sSymbol-Table
Francisco OrtinJuan Manuel Cueva
Computational JumpComputational Jump
• How can an application access to its interpreter computational environment?
• We have selected the Python programming language to implement the nitrO platform because of its:
Introspection capabilities: At runtime, the every application may inspect its variables, objects, attributes, methods and modules
Structural reflection capabilities: The previously-mentioned features an application has might be dynamically modified
Dynamic evaluation of code represented as strings: The exec function can dynamically evaluate code created at runtime
Francisco OrtinJuan Manuel Cueva
The The reifyreify Statement Statement
• Not needing to specify it, every language has the reify statement
• Inside a reify statement, Python code can be placed
• The generic interpreter recognizes every reify statement regardless the programming language being analyzed
• The generic interpreter will not process a reify statement as the rest of the code; it will:
The Python code inside the reify statement is taken as a string
This code is passed as an argument to the exec function The Python code is evaluated at the interpreter computational environment!
Francisco OrtinJuan Manuel Cueva
Non-Restrictive ReflectionNon-Restrictive Reflection
• Using Python introspection and structural reflection, application’s symbol-tables and language’s specification can be inspected/adapted
GenericInterpreter
User’s Application
Language-Specification
Application’sSymbol-
Table
a=10*2; b=a/-18; Reify <# write(str(vars)) vars["a"]=2 #> a; b; Reify <# code=“...” language["assignment"]. actions.append(code) #> a=10*2;
Specific language
Pythonlanguage
write(str(vars))vars["a"]=2
1) Introspection2) Structural Reflection
code=“...”language["assignment"]. actions.append(code)
3) Computational Reflection
Ap
plicati
on
Com
pu
tati
on
al En
vir
on
men
t
Inte
rpre
ter
Com
pu
tati
on
al
En
vir
on
men
t
Python becomes a1.- runtime2.- non-restrictive3.- language-neutral4.- three-levels-reflectivemeta-language
Francisco OrtinJuan Manuel Cueva
Language SpecificationLanguage Specification
• Language-Specification files describe: Scanner and parser rules with context-free
grammar rules Semantic specifications by means of Python code
MetaPython.ML describes a subset of the Python programming language:
Language = MetaPython
Scanner = { "Digit Token" digit -> "0"|"1"|"2"|"3"|"4"|"5"|"6"|"7"|"8"|"9" ;
"Integer Token" INTEGER -> digit moreDigits ;
"Float Token" FLOAT -> INTEGER "." INTEGER ;
"Zero or more digits token" moreDigits -> digit moreDigits | ;
"Character Token" char -> "a"|"b"|"c"|"d"|"e"|"f"|"g"|"h"|"i"|"j"| "k"|"l"|"m"|"n"|"ñ"|"o"|"p"|"q"|"r"|"s"|"t"|"u"|"v"|"w"|"x"|"y"|"z"| "á"|"é"|"í"|"ó"|"ú"| "A"|"B"|"C"|"D"|"E"|"F"|"G"|"H"|"I"|"J"|"K"|"L"|"M"|"N"|"Ñ"|"O"|"P"| "Q"|"R"|"S"|"T"|"U"|"V"|"W"|"X"|"Y"|"Z"|"Á"|"É"|"Í"|"Ó"|"Ú"|"_” ;...
Francisco OrtinJuan Manuel Cueva
Syntactic and Semantic SpecSyntactic and Semantic SpecParser = {
"Initial Free-Context Rule" S -> statement moreStatements <## Initial Code Needed in the Application Executionglobal classes,functionsclasses={} # Classes Symbol Tablefunctions={} # Function Symbol Tablenodes[1].execute()nodes[2].execute()#> ;
"Zero or more statements" moreStatements -> statement moreStatements <#nodes[1].execute()nodes[2].execute()#> | ;
"Python Statement" statement -> class <#nodes[1].execute() # Inserts the class into the ST#>
| function <#nodes[1].execute() # Inserts the class into the ST#>
| if | while | import | assignment | functionCall ;
"Class Spec." class -> CLASS ID OPENCURLYBRACE classBody CLOSECURLYBRACE...
Skip = { "\t"; "\n"; " "; }NotSkip = { }
Semantic actions
Syntactic rules(semantic rules derivatively suppressed)
Tokens automatically skipped
Tokens automatically appended
Francisco OrtinJuan Manuel Cueva
Sample ApplicationSample ApplicationApplication = "Sample App"Language = "MetaPython"
import string;import random; class MyClass {
def init(self) {self.calls=0;self.nestingLevel=1;}
def call(self) {self.calls=self.calls+1;}
def nestedCall(self) {self.calls=self.calls+1;temp=random.random()-(1.0-self.nestingLevel/10.0);if temp<0.5 {
self.nestingLevel=self.nestingLevel+1;self.nestedCall();self.nestingLevel=self.nestingLevel-1;}
}
}
object=MyClass();object.init();while 1 {
object.call();object.nestedCall();
}
Application and Language Description
Francisco OrtinJuan Manuel Cueva
Application ExecutionApplication Execution
• The platform offers a nitrO object, representing the system applications and languages (Facade)
• When the application execution takes place in the nitrO platform:
An application object is created in the nitrO.apps dictionary (with the key “Sample App”)
The MetaPython.ml language specification-file is located The language specification is translated into a object
structure; this is saved into the language application-object attribute
At runtime, the application symbol-table is located on its applicationGlobalContext attribute
Language Spec
language
Symbol Table
applicationGlobalContext
nitrO nitrO.apps[“Sample App”]apps
Francisco OrtinJuan Manuel Cueva
Application AdaptationApplication Adaptation
• Every application executed in the nitrO platform may access the nitrO “Facade” object and dynamically adapt:
An application symbol-table Introspection and Structural Reflection
A language specification Computational Reflection
• without any MOP-restrictive protocol!• in a language-independent way!
Francisco OrtinJuan Manuel Cueva
Dynamic Application WeavingDynamic Application WeavingApplication = "Time Aspect"Language = <# Language = JustAReifyStatement Scanner = {} Parser = { "Initial Free-Context Rule" S -> _REIFY_ <# nodes[1].execute() #> ; } Skip={ "\t"; "\n"; " "; } NotSkip = { } #>
reify <#def weave(app,nitrO): # Function that weaves an application if nitrO.apps.has_key(app): # This is just a MetaPython aspect if nitrO.apps[app].language.name=="MetaPython": codeBefore="""... """ codeAfter="""... """ actions=nitrO.apps[app].language.syntacticSpec["functionCall"].options[1].actions # Had the aspect been weaved? hadBeenWeaved=... if not(hadBeenWeaved): # Inserts the monitoring code actions.insert(0,SemanticAction(codeBefore)) actions.append(SemanticAction(codeAfter)) else: # Removes the monitoring code length=len(actions) for i in range(length): action=actions[length-i-1] if action.action==codeBefore or action.action==codeAfter: actions.remove(action) nitrO.shell.write("Application unweaved.")...nitrO.apps["Time Aspect"].weave=weave # Creates an application aspect-weaver#>
Language Specification inside the application file(just a reify statement)
Time-execution method-call monitoring
Removes the monitoring routines
# Application time-monitoring weavernitrO.executeFile(nitrO.dir+”time/timeAspect.na”)write(nitrO.describe())
nitrO.apps["Time Aspect"].weave("Sample App",nitrO)
Francisco OrtinJuan Manuel Cueva
Platform BenefitsPlatform Benefits
• No MOP-restrictions: the real computational jump overcomes the MOP-based adaptation limitations
• Language independence: The generic interpreter can interpreter any
previously-specified language The reify statement is part of every language
• What can be adapted: introspection, structural reflection and computational reflection
• Application interoperability: any application may access and reflectively modify another program being executed –whatever its language would be
• Expressiveness improvement: the way behavior is customized is not restricted to a framework that relies in method overriding; a complete meta-language (Python) might be used to adapt any other language’s feature
Francisco OrtinJuan Manuel Cueva
Runtime PerformanceRuntime Performance
• Runtime performance penalties are caused by the interpretation of every programming language
• However, many interpreted languages (Java, C# or even Python) are commercially employed due to optimization techniques such as JIT compilation
• As we always translate any language into Python code, a way of speeding up the execution of our platform’s applications in the following versions is using the interface of a Python-JIT compiler implementation
Platform download at:www.di.uniovi.es/reflection/lab/prototypes.html#nrrs
University of Oviedo Computer Science Department
Francisco OrtinJuan Manuel Cueva
The nitrO Reflective PlatformThe nitrO Reflective Platform
International Conference on International Conference on Software Engineering Research Software Engineering Research
and Practice (SERP)and Practice (SERP)
Session on Adaptable Software Session on Adaptable Software Architectures (ASA)Architectures (ASA)