关于MetaProgramming [DSL in Action节选]

  1. 云栖社区>
  2. 博客>
  3. 正文

关于MetaProgramming [DSL in Action节选]

狗尾巴呢 2012-08-05 09:14:00 浏览727
展开阅读全文

MOP

These dynamic behaviors are governed by the metaobject protocol ( MOP)  that  each  of  these  languages  implements  in  their  runtime.  The metaobject protocol of a language defines the semantics of the extensibility of the language artifacts. Take a look at the accompanying callout for a gentle introduction to the concept of  MOP in programming languages.

DEFINITION  A meta-object is an abstraction that manipulates the behavior  of other objects. In an  OOP language, a metaclass might be responsible for creating and manipulating classes. To do that, the metaclass needs to store all  information  that’s  relevant  to  the  class,  like  type,  interface,  methods, and extension objects.

A  meta-object  protocol  ( MOP) for a language defines the semantics of the extensibility of programs written in that language. The behavior of theprogram  is  determined  by  the  MOP,  including  aspects  of  the  program  that can be extended by the programmer during compile time or runtime.

Metaprogramming is the ability to write programs that generate new programs or that change  the  behavior  of  existing  programs. 

In  an  OO  language  like  Ruby  or  Groovy, metaprogramming implies capabilities that extend existing object models, add hooks to alter the behaviors of existing methods (or even classes), and synthesize new methods,  properties,  or  modules  during  runtime  through  introspection. 

Languages  like Lisp  use  macros  as  the  metaprogramming  tool  that  let  you  syntactically  extend  the language during the compilation stage. Although the primary form of metaprogramming that’s supported by Groovy or Ruby is runtime, Lisp metaprogramming is compile  time,  and  doesn’t  incur  any  runtime  overhead.  (Both  Groovy  and  Ruby  have library support for compile-time metaprogramming through explicit manipulation of the  AST s. But it’s nowhere near as elegant as Lisp.

Java also offers  metaprogramming  capabilities  through  annotation  processing   and  aspect-oriented programming ( AOP); it also defines all its extensibility mechanisms through its  MOP.

Statically  typed  languages  like  Haskell  and  OCaml  that  have  traditionally relied on pure embedded semantics for designing  DSL s now offer type-safe compile-time  metaprogramming  through  extensions  like  Template  Haskell  and  MetaOCaml respectively.  For  more  information,  see  http://www.haskell.org/th/  and http://www.metaocaml.org/

Runtime metaprogramming in DSL implementation

Why is metaprogramming support such an important feature for a language to host a DSL ? The answer is that because metaprogramming support makes a language exten-sible, the DSL  that you’ve implemented in an extensible language also becomes transi-tively extensible. 

wps_clip_image-10150

wps_clip_image-27118

Compile-time metaprogramming in DSL implementation

Compile-time  metaprogramming  lets  you  construct  and  manipulate  pro-grams during compile time. You can define new constructs and interact with the compiler to perform syntactic transformations and application-specific optimizations. with compile-time metaprogramming, you can grow a language seamlessly toward your domain syntax.

To use the most common form of compile-time metaprogramming you implement  syntactic  macros. 

Macro  implementations  vary  in  complexity  and  power,  from the  textual  macros  offered  by  C  preprocessors  to  the  sophisticated  AST -based  ones offered by variants of Lisp and some statically typed languages like Template Haskell and MetaOCaml.

Besides macros, some languages offer other preprocessor-based capabilities for compile-time metaprogramming, like the templates in C++, AOP, and annotation processing. Some languages like Groovy and Scala also have implementations of explicit compiler plugins, which provide some metaprogramming capabilities in the form of AST  manipulation.

C++: TEMPLATES

C++ offers templates as one of the most dominant protocols for metaprogramming. C++  templates  support  powerful  code-generation  mechanisms  through  manipulation  of data structures during compile time. This form of compile-time metaprogramming has been used quite successfully in scientific and numerical applications for generating inline versions of algorithms that employ techniques like loop unrolling for optimizing performance.

LISP   AND  C LOJURE:  MACROS

Lisp has the most sophisticated and complete support for compile-time metaprogramming,  through  its  system  of  macros.  Unlike  C  macros  that  have  limited  expressive power and that operate based on textual substitution, Lisp macros are powered by the full extensibility of the language.

JAVA :  ANNOTATION   PROCESSING AND  AOP  SUPPORT

Java also supports a limited form of compile-time metaprogramming through annotation processing and support for AOP . You can use annotations in a Java program that get processed during build-time. These annotations generate code that can supplement or alter existing program behavior.

AspectJ is the aspect-oriented extension to Java that offers a small  set  of  powerful  constructs  that  let  you  inject  additional  behavior  into  existing programs  through  bytecode  instrumentation.

LISP

CST  & AST

When  you  write  a  program  in  most  languages,  what  you’re  writing  is being  represented  as  the  concrete  syntax  tree  (CST ).  The CST   is  the faithful  representation  of  your  program,  including  the  white  spaces,  com-ments, and any metainformation you generate.

Your program is then passed through scanners, lexical analyzers, and parsers to generate what we call the abstract syntax tree (AST ). The AST  is the syntactic essence of your program that  gets  pipelined  into  the  next  phases  of  the  compilation  process.  It  goes through  the  usual  steps  of  transformation,  optimization,  and  code  genera-tion.

The parser of your language is primarily responsible for all such trans-formations that lead to the generation of the  AST  from the  CST .

Code as data

In Lisp, every program is a list structure, which is the  AST  of the code itself. As a result, code is seen as having the same representation and syntax as data. By standardizing on this simple protocol, the language publishes the abstract syntax to the programmer. This  abstract  syntax  is  simple—it’s  a  list.  Any  metaprogram  that  you  generate  using Lisp needs to conform only to this simple, standard representation.

Data as code

By using the  QUOTE special form, data syntax can be embedded easily into the code syntax.  Lisp  macros  are  good  examples  of  this  philosophy.  In  fact,  Lisp  extends  this paradigm  of  data  as  code  and  offers  a  full-blown  template  mechanism  for  writing metaprograms. In Common Lisp, we call this  quasiquotation . In Clojure, the same feature is implemented through  syntax quote ,  unquote, and splicing unquote .

 

MOP参考 

Kiczales,  Gregor,  Jim  des  Rivieres,  and  Daniel  G.  Bobrow.  1991.  The  Art  of  the  Metaobject Protocol. The  MIT  Press

网友评论

登录后评论
0/500
评论
狗尾巴呢
+ 关注