Tesis Doctoral - AD Universidad de Oviedo

Download Report

Transcript Tesis Doctoral - AD Universidad de Oviedo

University of Oviedo
Computer Science Department
The nitrO Reflective Platform
International Conference on
Software Engineering Research
and Practice (SERP)
Session on Adaptable Software
Architectures (ASA)
Juan Manuel Cueva
Francisco Ortin
Adaptability
• 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
Juan Manuel Cueva
Francisco Ortin
Reflection
• 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)
Juan Manuel Cueva
Francisco Ortin

Meta-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
Attaching objects to the metaobject (attachObject) implies
behavior adaptation
User Objects
Base
Level
Trace
Meta-Object
MetaXa
Example
Runs
Meta-Level
Semantics
Overriding
Interpreter
Juan Manuel Cueva
User’s
Application
Trace class that
overrides the messagepassing mechanism
Meta-Object
Protocol
MetaObject
attachObject(Object)
eventMethodEnter()
System class used to
modify the applications
semantics
Francisco Ortin
MOP 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
Juan Manuel Cueva
Francisco Ortin
Theoretical 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
Juan Manuel Cueva
Francisco Ortin
System 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
Juan Manuel Cueva
Francisco Ortin
System Architecture
SampleLang.ML
...
3) The language
specification is
translated into a
objects structure
User’s Application
Application = “Sample App”
Language = “Sample Lang”
Class MyClass {
// * App code
...
}
2) The language
specification file is
found in the system
8) If the application
modifies the language
semantics,
computational
reflection is achieved
6) If the application
reads its symbol-table,
introspection is
achieved
7) If the application
modifies its symboltable, structural
reflection is achieved
1) A user program
is about to be run
4) The user’s
application starts
running
Generic
Interpreter
Language-Specification
Objects Structure
Juan Manuel Cueva
5) While the
application is
running, a symboltable is used by the
interpreter
Application’s
Symbol-Table
Francisco Ortin
Computational 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 previouslymentioned 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
Juan Manuel Cueva
Francisco Ortin
The reify 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!
Juan Manuel Cueva
Francisco Ortin

Non-Restrictive Reflection
• Using Python introspection and structural reflection,
application’s symbol-tables and language’s specification can
be inspected/adapted
Python
language
3) Computational
Reflection
LanguageSpecification
Juan Manuel Cueva
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;
code=“...”
language["assignment"].
actions.append(code)
Python becomes a
1.- runtime
2.- non-restrictive
3.- language-neutral
4.- three-levels-reflective
meta-language
write(str(vars))
vars["a"]=2
Generic
Interpreter
1) Introspection
2) Structural
Reflection
Interpreter
Computational
Environment
Specific
language
Application
Computational Environment
User’s Application
Application’s
Symbol-Table
Francisco Ortin
Language 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"|"Á"|"É"|"Í"|"Ó"|"Ú"|"_” ;
...
Juan Manuel Cueva
Francisco Ortin
Syntactic and Semantic Spec
Parser = {
"Initial Free-Context Rule" S -> statement moreStatements <#
# Initial Code Needed in the Application Execution
global classes,functions
classes={} # Classes Symbol Table
functions={} # Function Symbol Table
nodes[1].execute()
nodes[2].execute()
#> ;
Semantic actions
"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
Syntactic rules
| while
(semantic rules derivatively
| import
suppressed)
| assignment
| functionCall ;
"Class Spec." class -> CLASS ID OPENCURLYBRACE classBody CLOSECURLYBRACE
...
Skip = { "\t";
NotSkip = { }
Juan Manuel Cueva
"\n"; " "; }
Tokens automatically skipped
Tokens automatically appended
Francisco Ortin
Sample Application
Application = "Sample App"
Language = "MetaPython"
Application and Language Description
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();
}
Juan Manuel Cueva
Francisco Ortin
Application 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 applicationobject attribute
At runtime, the application symbol-table is located on its
applicationGlobalContext attribute
language
nitrO
apps
nitrO.apps[“Sample App”]
applicationGlobalContext
Juan Manuel Cueva
Language
Spec
Symbol
Table
Francisco Ortin
Application 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!
Juan Manuel Cueva
Francisco Ortin
Dynamic Application Weaving
#nitrO.apps["Time
Application time-monitoring
Aspect"].weave("Sample
weaver
App",nitrO)
nitrO.executeFile(nitrO.dir+”time/timeAspect.na”)
write(nitrO.describe())
Application = "Time Aspect"
Language = <#
Language
= JustAReifyStatement
Scanner = {}
Parser = { "Initial Free-Context Rule" S -> _REIFY_ <#
nodes[1].execute()
#> ; }
Skip={ "\t"; "\n"; " "; } NotSkip = { }
#>
Language Specification
inside the application file
(just a reify statement)
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].action
# Had the aspect been weaved?
hadBeenWeaved=...
if not(hadBeenWeaved): # Inserts the monitoring code
Time-execution
actions.insert(0,SemanticAction(codeBefore))
actions.append(SemanticAction(codeAfter))
method-call monitoring
else: # Removes the monitoring code
length=len(actions)
for i in range(length):
Removes the
action=actions[length-i-1]
if action.action==codeBefore or action.action==codeAfter:
monitoring
actions.remove(action)
routines
nitrO.shell.write("Application unweaved.")
...
nitrO.apps["Time Aspect"].weave=weave # Creates an application aspect-weaver
#>
Juan Manuel Cueva
Francisco Ortin
Platform 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
Juan Manuel Cueva
Francisco Ortin
Runtime 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
Juan Manuel Cueva
Francisco Ortin
University of Oviedo
Computer Science Department
The nitrO Reflective Platform
International Conference on
Software Engineering Research
and Practice (SERP)
Session on Adaptable Software
Architectures (ASA)
Juan Manuel Cueva
Francisco Ortin