2008-08-21 13 views
6

J'ai essayé de comprendre comment les blocs Ruby travail, et de le faire que j'ai essayé de les mettre en œuvre en C.blocs Ruby/fermetures de Java en C

Un moyen facile à mettre en œuvre des fermetures est de passer void* à la pile englobante à la fonction de fermeture/fonction, mais les blocs Ruby semblent également gérer les retours et les déclarations de rupture de la portée qui utilise le bloc.

loop do 
    break i if (i >= 4000) 
    i *= 2 
end 

Je pense que l'une des propositions de fermeture pour Java fonctionne comme ça aussi. Alors, comment implémenteriez-vous Ruby-blocks/Java-closures en C?

+0

"Alors, comment implémenteriez-vous Ruby-blocks/Java-closures en C?" Au moins jusqu'à la sortie de Java 7, les fermetures Java n'existent pas. –

+0

Oui, c'est pourquoi j'ai dit "propositions de fermetures pour Java" juste avant. –

Répondre

10

Le concept de fermetures nécessite le concept de contextes. Le contexte de C est basé sur la pile et les registres de la CPU, donc pour créer un bloc/fermeture, vous devez pouvoir manipuler le pointeur de la pile de manière correcte (et réentrante), et stocker/restaurer les registres si nécessaire.

La façon dont ceci est fait par les interprètes ou les machines virtuelles est d'avoir une structure context ou quelque chose de similaire, et de ne pas utiliser la pile et les registres directement. Cette structure conserve la trace d'une pile et éventuellement de certains registres, si vous concevez une machine virtuelle basée sur un registre. Au moins, c'est le moyen le plus simple de le faire (bien que légèrement moins performant que de cartographier correctement les choses).

2

Il y a une bonne série de diapositives sur les blocs Ruby dans le cadre des « Rails avec passion » bien sûr:

Ruby_Blocks.pdf

Ce couvre représentant un bloc, la façon dont ils sont transmis des arguments et exécutés, et même plus dans des choses comme les objets Proc. C'est très clairement expliqué.

Il pourrait alors être intéressant de voir comment les gars de JRuby les ont traités dans leur analyse de Java. Jetez un oeil à la source au codehaus.

3

Je ne l'ai pas implémenté réellement, alors prenez-le avec un sac de sel.

La fermeture comporte deux parties: l'environnement de données et l'environnement de code. Comme vous l'avez dit, vous pouvez probablement passer un vide * pour gérer les références aux données. Vous pourriez probablement utiliser setjmp et longjmp pour implémenter les sauts de flux de contrôle non-linéaire que requiert la pause Ruby.

Si vous voulez des fermetures, vous devriez probablement programmer dans une langue qui les supporte réellement. :-)

MISE À JOUR: Des choses intéressantes se passent à Clang. Ils ont prototypé une fermeture pour C. http://lists.cs.uiuc.edu/pipermail/cfe-dev/2008-August/002670.html pourrait s'avérer être une lecture intéressante.