8
votes

Transformer Lisp sur C ++

Je travaille sur une langue de jouets qui compile sur C ++ sur la base de LISP (très petit sous-ensemble de schéma), j'essaie de déterminer comment représenter Let expression, xxx

au début Je pensais exécuter tous les exprs puis renvoyer le dernier mais le retour va tuer ma capacité à nicher des expressions, quelle serait la voie à suivre pour représenter la lettre?

En outre, toute ressource sur la source de la transformation de la source à la source est évaluée. , J'ai googlé mais tout ce que je pouvais fier, c'est le compilateur de schéma de 90 min.


1 commentaires

Voici un article de blog qui pourrait aider, ce blogueur a écrit un groupe d'articles sur le sujet de la compilation et celui-ci est lié aux fermetures de traitement. C'était juste affiché à Hn et m'a fait réfléchir à cette question: Matt.might.net/ Articles / Conversion de fermeture C'est une technique plus avancée que la naïve que j'ai décrite mais c'est écrit assez clairement.


3 Réponses :


-1
votes

Si vous recherchez des outils pour vous aider à la traduction source à source, je recommanderais antlr . C'est très excellent.

Toutefois, vous devrez réfléchir à la façon de traduire d'une langue de typée (LISP) à une langue (C) sans loosité (C). Par exemple, dans votre question, quel est le type de 10 ? Un court ? Un int ? Un double ?


1 commentaires

J'ai mon propre système d'objet 10 est un int sur le côté C ++, je sais ce que c'est pendant le temps d'exécution



9
votes

Un moyen d'étendre laisser est de le traiter comme un lambda : xxx

puis, transformez ceci en une fonction et un Call correspondant en C ++: xxx

donc dans un contexte plus important: xxx

devient xxx

Il y a beaucoup plus de détails, tels que besoin d'accéder à des variables lexicales en dehors du let dans le laisser . Étant donné que C ++ n'a pas de fonctions lexiquement imbriquées (contrairement à Pascal, par exemple), cela nécessitera une mise en œuvre supplémentaire.


0 commentaires

4
votes

Je vais essayer d'expliquer une approche naïve de la compilation imbriquée Lambda s. Depuis l'explication de Greg d'expansion laisse dans un lambda est très bon, je ne traiterai pas laisser du tout, je suppose que laisser est une forme ou une macro dérivée et est étendue dans un lambda formulaire qui est Appelé immédiatement.

Compiler des fonctions Lisp ou Scheme directement dans les fonctions C ou C ++ sera délicat en raison des problèmes d'autres affiches soulevées. Cela dépend de l'approche, le C ou C ++ résultant ne sera pas reconnaissable (ni même très lisible).

J'ai écrit un compilateur LISP-TO-C après la finition de la structure et de l'interprétation des programmes informatiques (c'est l'un des derniers exercices, et j'ai triché et vient d'écrire un traducteur du code d'octets SICP à C). Le sous-ensemble de C qu'elle émise n'a pas utilisé de fonctions C pour gérer les fonctions LISP du tout. C'est parce que le Enregistrer la langue de la machine au chapitre 5 de la SICP est vraiment inférieur que c.

supposant que vous avez une forme d'environnement, qui lient les noms à des valeurs, vous pouvez définir le creux de fonction appelant comme ceci: étendre l'environnement que la fonction a été définie avec les paramètres formels liés aux arguments, puis évaluez le corps de la fonction dans ce nouvel environnement.

Dans le compilateur de SICP, l'environnement est détenu dans une variable globale et il y a d'autres Variables globales tenant la liste des arguments pour un appel de la fonction, comme ainsi que l'objet de procédure appelé (l'objet de procédure inclut un pointeur à l'environnement dans lequel il a été défini) et une étiquette pour sauter lorsqu'une fonction retourne.

Gardez à l'esprit que lorsque vous compilent une expression lambda sont deux composants syntaxiques que vous connaissez à la compilation: le formel paramètres et le corps du lambda .

Lorsqu'une fonction est compilée, le code émis ressemble à quelque chose comme ce pseudocode: xxx

... où * env * et * argl * sont les variables globales tenant le Liste de l'environnement et des arguments, et EXTENDY est une fonction (ceci peut être une fonction C ++ appropriée) qui étend l'environnement * env * par jumelage des noms dans * argl * avec des valeurs dans [formals] .

alors, lorsque le code compilé est exécuté, et il y a un appel à cette lambda ailleurs dans votre code, la convention appelante doit mettre Le résultat de l'évaluation de la liste d'arguments dans la variable * argl * , mettez l'étiquette de retour dans la variable * Continuer * , puis passez à une étiquette /code >.

lambda lambda s, le code émis semblerait quelque chose comme ceci: xxx

Ceci est un peu difficile à expliquer, et je suis sûr que j'ai fait un embrouillé travail de celui-ci. Je ne peux pas penser à un exemple décent qui ne me concerne pas fondamentalement de décrire le chapitre 5 du SICP. Puisque j'ai passé le temps d'écrire cette réponse, je vais le poster, mais je suis vraiment désolé s'il est désespérément déroutant.

Je recommande fortement sicp et Lisp en petites pièces .

SICP couvre une interprétation métacolirculeuse pour les débutants, ainsi qu'un certain nombre de variantes sur l'interprète et un compilateur de code d'octet que j'ai réussi à obscurcir et caprice ci-dessus. Ce n'est que les deux derniers chapitres, les 3 premiers chapitres sont tout aussi bons. C'est un livre merveilleux. Absolument lu si vous ne l'avez pas encore fait.

LISP comprend un certain nombre d'interprètes écrits dans un schéma, un compilateur au code octet et un compilateur à C. Je suis au milieu de cela et peut dire avec Confidence C'est un livre profond et riche valant bien le temps de toute personne intéressée par la mise en œuvre du LISP. Cela peut être un peu daté de ce point, mais pour un débutant comme moi, il est toujours précieux. Il est plus avancé que SICP, alors méfiez-vous. Il incombe à un chapitre au milieu sur la sémantique dénotationnationnose qui allait fondamentalement sur ma tête.

Quelques autres notes:

Compilateur auto-hébergement auto-hébergement de Darius Bacon

Lambda Soulever , qui est une technique plus avancée que je pense que Marc Pertey utilise


1 commentaires

+1 Pour souligner que c'est beaucoup plus compliqué que de traduire laisser à lambda / application