Tema 5: Macros - DCCIA. Departamento de Ciencia de la ... · • Las macros son un meta-lenguaje,...

23
Tema 5: Macros Sesión 14: Macros miércoles 23 de marzo de 2011

Transcript of Tema 5: Macros - DCCIA. Departamento de Ciencia de la ... · • Las macros son un meta-lenguaje,...

Tema 5: Macros

Sesión 14: Macros

miércoles 23 de marzo de 2011

Hoy veremos...

• Conceptos generales

• Quasiquotation

• Macros en Scheme

• Ejemplos de macros

miércoles 23 de marzo de 2011

Referencias

• Capítulo 3.7 Programming Language Pragmatics: Macro Expansion

miércoles 23 de marzo de 2011

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

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

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

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

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

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

Macros en Scheme

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

• Sintaxis de una macro:

• Ejemplo: mi-or

(define-syntax <keyword> (syntax-rules (<literales>) ((<patron-1> <plantilla-1>) ... (<patron-n> <plantilla-n>))))

(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

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 estas mismas reglas.

miércoles 23 de marzo de 2011

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

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

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

Macro make-procedure

(define-syntax make-procedure (syntax-rules () ((make-procedure (x ...) expr ...) (lambda (x ...) expr ...))))

miércoles 23 de marzo de 2011

Macro mi-let

miércoles 23 de marzo de 2011

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

Macro mi-cond

miércoles 23 de marzo de 2011

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

Macro multi-print (paradigma procedural)

miércoles 23 de marzo de 2011

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

Macro when (paradigma procedural)

miércoles 23 de marzo de 2011

Macro when (paradigma procedural)

(define-syntax when (syntax-rules () ((when condition expr1 expr2 ...) (if condition (begin expr1 expr2 ...) #f))))

miércoles 23 de marzo de 2011