2010-08-13 22 views
39

Últimamente en el trabajo, he estado haciendo algunas traducciones de Makefiles a un sistema de compilación alternativo. He visto algunos códigos Make bastante bonitos en algunos lugares usando mapas funcionales, filtros y construcciones foreach. Esto me sorprendió ya que creo que los scripts de compilación deben ser tan declarativos como sea posible.¿Los archivos MAKE están completos?

De todos modos, esto me hizo pensar: es el lenguaje Makefile (digamos que la última versión de GNU es específica) ¿Turing está completo?

+1

Sin su descripción, le preguntaría si estaba resolviendo una apuesta :) –

+0

Está en Unix, tiene una sintaxis pilosa, y es sorprendentemente poderosa. La mayoría de las cosas así son Turing-completas. No me sorprendí hace veinte años cuando alguien me mostró una máquina Vi macro Turing. –

+3

Puede pagar todo lo que desee, incluida una máquina de Turing, durante la construcción de cadenas. Técnicamente has perdido en este punto. (Tenemos llamadas Perl en nuestros Makefiles. Suspiro). –

Respuesta

40

Sí, consulte this. Una vez que tienes lambda, todo está cuesta abajo desde allí.

Aquí está un ejemplo de Fibonacci plagiarized

Esto debería ser suficiente para construir una base para más generalidad (Tengo que volver al trabajo, o me gustaría jugar más.)

dec = $(patsubst .%,%,$1) 

not = $(if $1,,.) 

lteq = $(if $1,$(if $(findstring $1,$2),.,),.) 
gteq = $(if $2,$(if $(findstring $2,$1),.,),.) 
eq = $(and $(call lteq,$1,$2),$(call gteq,$1,$2)) 
lt = $(and $(call lteq,$1,$2),$(call not,$(call gteq,$1,$2))) 

add = $1$2 
sub = $(if $(call not,$2),$1,$(call sub,$(call dec,$1),$(call dec,$2))) 
mul = $(if $(call not,$2),$2,$(call add,$1,$(call mul,$1,$(call dec,$2)))) 
fibo = $(if $(call lt,$1,..),$1,$(call add,$(call fibo,$(call dec,$1)),$(call fibo,$(call sub,$1,..)))) 
fact = $(if $(call lt,$1,..),.,$(call mul,$1,$(call fact,$(call dec,$1)))) 

numeral = $(words $(subst .,. ,$1)) 

go = $(or $(info $(call numeral,$(call mul,$1,$1)) $(call numeral,$(call fibo,$1)) $(call numeral,$(call fact,$1))),$(call go,.$1)) 

_ := $(call go,) 

Esto imprime cuadrados, números de Fibonacci y factoriales. Parece que hay un límite de 16 bits para los tamaños de los números. Gorrón.

+1

Una vez que tiene lambda, entonces creo que puede crear un Y-combinator que le da recursividad. Como dices, todo cuesta abajo desde allí. –

+9

Eso es increíble. Y aterrador. Sobre todo aterrador. –

+0

@Jorg Oleg es un tipo impresionante pero atemorizador. Sobre todo aterrador. Lee las otras cosas que tiene. – deinst

6

Ahora, para una respuesta negativa: GNU hacer bloques activamente algunos mecanismos para crear recursión:

1) Recursively expanded variables

no son recursiva en el sentido de "función recursiva": no pueden ser definidos en términos de sí mismos:

Actually make detects the infinite loop and reports an error. 

(no veo cómo lo que les podría ser útil en la práctica, por cierto.)

2) Rule chaining

no puede ser recursivo, ya sea:

No single implicit rule can appear more than once in a chain. (...) 
This constraint has the added benefit of preventing any infinite loop 
in the search for an implicit rule chain. 

(he perdido mucho tiempo por este durante la depuración mis Makefile - además de todas las otras cosas que hacen difícil de archivos make mantener.)

PS para un proyecto reciente escribí a patch to GNU make 3.82 que elimina esta limitación con una nueva opción -M (ver discussion). Funciona bien para mí.

+0

Esto es interesante, pero me sorprendería mucho si make pudiera detectar siempre las macros recursivas en presencia de algo como $ (eval). –

Cuestiones relacionadas