Dans Article précédent, j'ai introduit un outil pour exécuter et archiver le code source à la fois. Présentation de cette fois est un outil qui compile nativement Hy pour créer des fichiers exécutables et des bibliothèques partagées. Vous pouvez également le convertir en langage Python ou C. Il est enregistré dans PyPI sous le nom HyCC. Cependant, il existe encore une possibilité de ** bogue inattendu **, veuillez donc l'utiliser en ** auto-responsabilité **. À propos, ** tous sont implémentés dans Hy **.
Veuillez installer à partir de pip
.
** Cependant, le fonctionnement dans l'environnement Windows n'a pas été confirmé. ** **
$ pip install hycc
~~ De plus, si la dernière version de PyPI est Hy (v0.12.1), une erreur due à un bogue dans Hy peut se produire dans certains codes, veuillez donc installer la dernière version de Github. ~~ ** PostScript 01/07/2017: Ce travail n'est plus nécessaire en raison de la mise à jour de Hy et HyCC. **
Maintenant que la préparation est terminée, prenons le code suivant comme exemple.
hello.hy
(defn hello []
(print "hello!"))
(defmain [&rest args]
(hello))
$ hycc hello.hy
Cela créera un exécutable binaire appelé «bonjour» dans le répertoire courant.
$ ./hello
hello!
Construisez avec l'option --shared
.
$ hycc hello.hy --shared
Cela créera un objet partagé appelé «hello.so» dans le répertoire courant. Python a la capacité d'importer des objets partagés en tant que modules, mais Hy est bien sûr le même. Par conséquent, ce "hello.so" peut être utilisé comme suit.
Hy pour bonjour.importer donc
(import hello)
(hello.hello)
; >hello!
Bonjour de Python.importer donc
import hello
hello.hello()
# >hello!
Les modules et exécutables compilés en mode natif sont ** environ 2 à 8 fois plus rapides **. Je pense donc que c'est plus utile que d'utiliser hyc
pour compiler l'octet dans un fichier .pyc
. Et bien sûr ** plus rapide que Python **. De plus, Cython est utilisé en interne, mais l'image de la vitesse est la suivante.
** C <Cython (avec spécification de type) << Cython (sans spécification de type) <HyCC <Python <Hy **
Il est généralement ** compatible vers le haut avec hyc
**, mais il y a une mise en garde **. Puisqu'il est lié au mécanisme interne, je vais l'expliquer tout en expliquant le mécanisme de ce qui suit.
En gros, le code Hy est converti en Python, converti en C via Cython et compilé. Cependant, comme mentionné dans Dernier message, le code Python généré en utilisant le hy2py
fourni en standard avec Hy. ** Ne fonctionne pas tel quel **. Par conséquent, il n'est pas possible de simplement «hy2py» et «cythoniser».
En premier lieu ** Pourquoi le code généré par «hy2py» ne fonctionne-t-il pas **? Parce que Python utilise un identifiant invalide. Les identifiants non valides en Python sont:
Prenez le code suivant comme exemple.
sample.hy
(reduce + [1 2 3])
; > 6
La conversion avec «hy2py» donne ce qui suit.
Code que hy2py crache
from hy.core.language import reduce
from hy.core.shadow import +
# +Est un identifiant invalide
reduce(+, [1, 2, 3])
Ici, «+» est le 2 ci-dessus. Parce que cela correspond à, c'est inutile. Le simple fait de le remplacer par un autre nom valide, par exemple «add», ne fonctionnera pas.
Du code que hy2py crache+Remplacer par ajouter
from hy.core.language import reduce
from hy.core.shadow import add
# ImportError
reduce(add, [1, 2, 3])
De toute évidence, le module hy.core.shadow
n'a pas le nom ʻadd défini, donc ce sera ʻImportError
. HyCC génère d'abord le code Python suivant à partir de la source Hy pour résoudre ce problème.
Voie HyCC
import hy.core.language as _
reduce = _.getattr("reduce")
import hy.core.shadow as _
+ = _.getattr("+")
reduce(+, [1, 2, 3])
Ce code est équivalent au code que «hy2py» crache, mais vous pouvez remplacer «+» par n'importe quel nom. HyCC évite les erreurs en combinant correctement l'accès au niveau AST et l'accès au niveau du code source. De même, l'accès membre de l'objet est réécrit avec getattr
et setattr
.
C'est la précaution lors de l'utilisation de HyCC que j'ai mentionnée plus tôt. Comme expliqué jusqu'à présent, HyCC remplace les identifiants invalides par des identifiants valides avec une certaine ingéniosité. Pour le moment, il n'y a qu'un seul effet secondaire ou problème.
Mauvais gars HyCC
(def hoge/fuga 0)
(print (get (globals) "hoge/fuga"))
; > 0
Le code ci-dessus est converti par HyCC en code Python suivant.
Code généré par HyCC
from __future__ import print_function
import hy
hogex2Ffuga = 0L
print(globals()[u'hoge/fuga'])
Vous pouvez ignorer l'ajout de certaines importations. Dans le code Hy original, hoge / fuga
était un nom invalide en Python. Par conséquent, il est remplacé par «hogex2Ffuga» dans le code généré par HyCC.
L'exécution de ce code entraînera l'erreur suivante.
File "test.py", line 4, in <module>
print(globals()[u'hoge/fuga'])
KeyError: u'hoge/fuga'
Avez-vous compris? L'effet négatif du remplacement d'un identifiant invalide par un identifiant valide est que les modules globals
, locals
et ʻinspect` peuvent ne pas fonctionner correctement dans certains cas.
Nous envisageons quelques contre-mesures pour ce problème, mais ** Hy lui-même a déjà un problème similaire ** en premier lieu. Dans Hy, hoge!
Est remplacé par hoge_bang
et hoge? ʻEst remplacé par ʻis_hoge
au stade de l'analyse syntaxique. Par conséquent, le code suivant ne fonctionne pas correctement.
Hy et méchant
(def hoge! 0)
(print (get (globals) "hoge!"))
; > KeyError!
Par conséquent, l'utilisation de «globals», etc. peut être considérée comme ** des précautions lors de l'utilisation de HyCC plutôt que des précautions lors de l'utilisation de HyCC **.
*** PostScript 04/06/2017 ***
** Pris en charge par la mise à jour! ** Plus précisément, l'erreur de clé est évitée en enveloppant globals
et locaux
dans une classe mystère comme dict. Comme d'habitude, le module ʻinspect ne fonctionne pas correctement, mais ** Cython lui-même ne prend pas en charge ʻinspect
**, donc je ne peux rien y faire. Pour plus de détails, reportez-vous à This Commit.
HyCC a également une fonction pour convertir de Hy en Python comme hy2py
.
$ hycc hello.hy --python
Cela affichera hello.py
dans le répertoire courant. Si vous faites attention aux notes ci-dessus, cela fonctionnera correctement contrairement au code produit par ** hy2py
**. Étonnamment, cette fonctionnalité peut être plus demandée. De même, il peut être converti en langage C avec l'option --clang
, mais il est délicat de savoir s'il peut être utilisé.
Comme je l'ai écrit dans problèmes github, est-ce une spécification Python? Lors de l'obtention d'un sous-module avec gettatr
pour un objet module Cela semble être une «erreur d'attribut» si le sous-module contient une bibliothèque partagée. Je réfléchis à comment y faire face.
Introduction de Outil de compilation native de Hy. Tout le développement se fait sur github, alors n'hésitez pas à Pururiku Vous pouvez lancer des pulls) ou issues. Bien entendu, les commentaires ici sont également les bienvenus. Hy est encore un putain de langage mineur en développement, mais j'espère qu'il deviendra plus sophistiqué à mesure que le nombre d'utilisateurs augmentera et que les discussions deviendront plus actives. Merci d'avoir lu jusqu'ici.
Recommended Posts