s14 Macros

Embed Size (px)

Citation preview

  • 8/19/2019 s14 Macros

    1/23

     Tema 5: Macros

    Sesión 14: Macros

    miércoles 23 de marzo de 2011

  • 8/19/2019 s14 Macros

    2/23

    Hoy veremos...

    • Conceptos generales

    • Quasiquotation

    • Macros en Scheme

    • Ejemplos de macros

    miércoles 23 de marzo de 2011

  • 8/19/2019 s14 Macros

    3/23

    Referencias

    • Capítulo 3.7 Programming Language Pragmatics: Macro Expansion

    miércoles 23 de marzo de 2011

  • 8/19/2019 s14 Macros

    4/23

    Definición de macro

    • Una macro consiste en una plantilla o meta-expresión que define un patrón

    de sustitución formado por unas variables libres y unas expresiones

    textuales.

    • Es una técnica de generación de código

    • Se realiza en la fase de preprocesamiento (en lenguajes compilados como C

    o C++)

    • Previamente a la evaluación de la expresión (en lenguajes interpretados)

    • Las macros son un meta-lenguaje, en el sentido de que permiten controlar y

    definir expresiones del propio lenguaje

    • No están sometidas a la sintaxis del lenguaje

    miércoles 23 de marzo de 2011

  • 8/19/2019 s14 Macros

    5/23

    Evolución histórica de las macros

    • Orígen de las macros: ensamblador

    • Se incorporan en lenguajes más próximos al ensamblador como C y en

    lenguajes avanzados como LISP o Scheme como una posibilidad de

    extender el lenguaje

    • En la actualidad no se usan demasiado, aunque su característica de meta-

    programación ha dejado una huella muy importante en los lenguajes de

    programación:

    • Anotaciones en Java

    • Scaffolding en Ruby & Rails

    • Herramientas de MDA de generación automática de código

    miércoles 23 de marzo de 2011

  • 8/19/2019 s14 Macros

    6/23

    Macros en C

    • Ejemplos de Macros:

    • Una llamada a la macro:

    • Se sustituirá (expansión de la macro) por:

    #define LINE_LEN 80

    #define MAX(a,b) ((a) > (b) ? (a) : (b))

    #define SWAP(a,b) {int t = (a); (a) = (b); (b) = t;}

    x = MAX(p+q, r+s);

    x = ((p+q) > (r+s) ? (p+q) : (r+s))

    miércoles 23 de marzo de 2011

  • 8/19/2019 s14 Macros

    7/23

    Las macros permiten definir nuevos lenguajes

    • Ejemplo en C:

    • Lo probamos:

    • Esta posibilidad es mucho más potente en las macros de Scheme

    • Lenguajes de dominio: las universidades y departamentos de investigación

    inventan lenguajes adaptados especificamente a dominios específicos como

    robótica. Es muy fácil diseñar prototipos de estos lenguajes con las macros

    de Scheme

    #define then

    #define begin {

    #define end ;}

    if (i > 0) then  begin

      a = 1;

      b = 2

      end

    miércoles 23 de marzo de 2011

  • 8/19/2019 s14 Macros

    8/23

    Problemas de la expansión en C

    • El preprocesador de C extiende la macro de forma ciega sin tener ninguna

    relación con el proceso de compilación posterior

    • Esto puede producir errores. Por ejemplo, si llamamos a MAX(x++, y++) la

    expansión de la macro produce el siguiente resultado:

    • LISP y Scheme utilizan las llamadas macros higiénicas que encapsulan

    implícitamente sus argumentos y evitan los errores de las macros de C

    ((a++) > (b++) ? (a++) : (b++))

    miércoles 23 de marzo de 2011

  • 8/19/2019 s14 Macros

    9/23

    Quasiquotation

    • La forma especial quasiquote junto con unquote permite evaluar de forma

    arbitraria las expresiones que nos interesan en una lista:

    • Se utiliza el símbolo backquote y la coma:

    (define bar 2)

    (quasiquote (foo (unquote bar) baz)) --> (foo 2 baz)

    `(foo ,bar baz) --> (foo 2 baz)

    (define a 2)

    (define b 'hola)

    '(1 a b)

    (quasiquote (1 ,a ,b))

    `(1 ,a ,b)

    `(1 ,a ,b ,c)

    `(1 ,+ ,-)

    miércoles 23 de marzo de 2011

  • 8/19/2019 s14 Macros

    10/23

    Macros en Scheme

    • Se basan en las formas especiales define-syntax y syntax-rules

    • Sintaxis de una macro:

    • Ejemplo: mi-or

    (define-syntax

      (syntax-rules ()  (( )

      ...

      ( ))))

    (define-syntax mi-or

      (syntax-rules ()

      ((mi-or) #t)

      ((mi-or e) e)

      ((mi-or e1 e2 e3 ...)

      (if e1 #t (mi-or e2 e3 ...)))))

    miércoles 23 de marzo de 2011

  • 8/19/2019 s14 Macros

    11/23

    Reglas de evaluación de una macro

    • Para evaluar una llamada a una macro (op exp_1 ... exp_n) debemos

    seguir las siguientes reglas:

    • Buscar la definición de la macro. Buscar la forma especial define-

    syntax en la que aparece op como clave.

    • Emparejar. Buscar en la definición de la macro la regla sintáctica con la

    que es posible emparejar la expresión (op exp_1 ... exp_n) que

    estamos evaluando. Si hay más de una regla con la que se puede

    emparejar la expresión, escogemos la primera de ellas.

    • Transformar. Aplicar la regla para transformar la expresión.

    • Evaluar. Evaluar la expresión resultante. En el caso en que la expresión

    resultante contenga una llamada a una macro se evaluará siguiendo estasmismas reglas.

    miércoles 23 de marzo de 2011

  • 8/19/2019 s14 Macros

    12/23

    Expansión de una macro

    • Expansión de la llamada a la macro:

    (mi-or (equal? x 2) #f #t (equal? y 3))

    miércoles 23 de marzo de 2011

  • 8/19/2019 s14 Macros

    13/23

    Sintaxis alternativas válidas

    (define-syntax mi-or

      (syntax-rules ()

      ((_) #t)

      ((_ e) e)

      ((_ e1 e2 e3 ...)

      (if e1 #t (mi-or e2 e3 ...)))))

    (define-syntax mi-or

      (syntax-rules ()

      ((op) #t)

      ((op e) e)  ((op e1 e2 e3 ...)

      (if e1 #t (mi-or e2 e3 ...)))))

    miércoles 23 de marzo de 2011

  • 8/19/2019 s14 Macros

    14/23

    Depuración de macros

    (define-syntax mi-or

      (syntax-rules ()

      ((op) ‘#t)

      ((op e) ‘e)  ((op e1 e2 e3 ...)

      ‘(if e1 #t (mi-or e2 e3 ...)))))

    miércoles 23 de marzo de 2011

  • 8/19/2019 s14 Macros

    15/23

    Macro make-procedure

    (define-syntax make-procedure

      (syntax-rules ()

      ((make-procedure (x ...) expr ...)

      (lambda (x ...) expr ...))))

    miércoles 23 de marzo de 2011

  • 8/19/2019 s14 Macros

    16/23

    Macro mi-let

    miércoles 23 de marzo de 2011

  • 8/19/2019 s14 Macros

    17/23

    Macro mi-let

    (define-syntax mi-let

      (syntax-rules ()

      ((mi-let ((x v) ...) e ...)

      ((lambda (x ...) e ...) v ...))))

    miércoles 23 de marzo de 2011

  • 8/19/2019 s14 Macros

    18/23

    Macro mi-cond

    miércoles 23 de marzo de 2011

  • 8/19/2019 s14 Macros

    19/23

    Macro mi-cond

    (define-syntax mi-cond

      (syntax-rules (=> else)

      ((mi-cond (else => expr))

      expr)

      ((mi-cond (test1 => expr1))

      (if test1 expr1))  ((mi-cond (test1 => expr1) (test2 => expr2) ...)

      (if test1 expr1 (mi-cond (test2 => expr2) ...)))))

    miércoles 23 de marzo de 2011

  • 8/19/2019 s14 Macros

    20/23

    Macro multi-print (paradigma procedural)

    miércoles 23 de marzo de 2011

  • 8/19/2019 s14 Macros

    21/23

    Macro multi-print (paradigma procedural)

    (define-syntax multi-print

      (syntax-rules ()

      ((multi-print arg1 arg2 ...)

    (begin (print arg1)

      (newline)

      (multi-print arg2 ...)))  ((multi-print) #t)))

    miércoles 23 de marzo de 2011

  • 8/19/2019 s14 Macros

    22/23

    Macro when (paradigma procedural)

    miércoles 23 de marzo de 2011

  • 8/19/2019 s14 Macros

    23/23

    Macro when (paradigma procedural)

    (define-syntax when

      (syntax-rules ()

      ((when condition expr1 expr2 ...)

      (if condition (begin expr1 expr2 ...) #f))))