Sur la base d'un commentaire de George Edison à cette question , écrivez le plus petit interprète auto-interprète.
- Vous pouvez utiliser la langue de votre choix.
- Les langues vides ne comptent pas. Votre programme doit comporter au moins deux caractères.
- Le programme n'a pas besoin d'interpréter la langue entière , juste un sous-ensemble complet de Turing de fonctionnalités linguistiques (qui contient l'interpréteur).
- Les quines ne comptent pas.
- N'utilisez pas la fonction intégrée de votre langue
eval
ou l'équivalent. Il en va de mêmeapply
, etc.
code-golf
interpreter
Hoa Long Tam
la source
la source
/usr/bin/cat
) qu'en est-il de Turing-complétude?sexp
analyseur.Réponses:
CI - 260
320 → 260: Poussez des mappages de caractère à instruction simples, puis repliez-les. Cela réduit de moitié la taille du code par cas (il y a 18 cas), mais coûte 30 caractères pour faire le pliage.
Ceci est une autre de mes langues construites (interprète de base hébergé sur Gist ). Il est unique en ce sens que le langage réifie les fragments de code. Autrement dit, les chaînes d'instructions dans ce langage basé sur la pile sont utilisées dans le même sens que les structures de données ou les fermetures dans d'autres langues:
L'interpréteur construit un fragment de code de l'ensemble du programme avant de l'exécuter, il peut donc également être considéré comme un compilateur. Pour cette raison, l' empilement de l'interpréteur n'entraîne pas de surcharge d'exécution exponentielle.
L'interpréteur dérive tous ses opérateurs directement de l'interpréteur hôte. Cependant, il effectue l'analyse par lui-même, donc la majorité du code n'est que des séquences qui traduisent les caractères dans leurs littéraux de code respectifs. Ce n'est pas la même chose que l'utilisation
eval
, mais cela révèle à quel point toute implémentation de langage de programmation dépend de la sémantique de son langage / architecture hôte.Référence du langage:
Obtenez l'interprète ici
Blocs
(
...)
Créez un "bloc", qui est en fait une liste d'instructions sans contexte. En interne, il pourrait même s'agir d'un code machine.
bloc
$
Appelez un bloc. L'appelé reçoit la pile globale, qui comprend le bloc appelé.
valeur
^
Soulevez une valeur. À savoir, le transformer en un bloc qui pousse cette valeur.
Exemple :
block1 block2
&
Joignez deux blocs, en formant un qui s'exécute les deux en séquence.
Exemple :
Manipulation de pile
n
c
Copiez la nième valeur de la pile.
Exemple :
n
p
Cueillez la nième valeur de la pile (supprimez-la et amenez-la au premier plan).
Exemple :
n
d
Supprimez n valeurs de la pile.
0d
est un no-op.Exemple :
Opérateurs relationnels
ab (on_true) (on_false)
=
Testez si a est égal à b. Consommez tout sauf le premier argument, et appelez on_true ou on_false. Si un argument est nul et que l'autre est de tout autre type, le résultat sera faux. Sinon, a et b doivent être des entiers.
Exemple :
ab (on_true) (on_false)
<
Testez si a est inférieur à b. a et b doivent être des entiers.
Exemple :
ab (on_true) (on_false)
>
Testez si a est supérieur à b. a et b doivent être des entiers.
Exemple :
a lo hi (on_true) (on_false)
~
Testez si lo <= a <= hi. a, lo et hi doivent être des entiers.
Exemple :
E / S
c
.
Mettez le personnage c (en le consommant de la pile).
,
Obtenez un personnage et poussez-le dans la pile. Si la fin du fichier est atteinte, -1 est poussé.
c
!
Oubliez un personnage. Tout comme ungetc en C, un seul pushback est autorisé.
Littéraux entiers
'c
Poussez le caractère c.
[0-9] +
Appuyez sur un entier décimal.
Arithmétique
+
-
un B
*
Additionnez / soustrayez / multipliez deux nombres.
Exemple :
un B
/
un B
%
Division et module. Contrairement à C, ils arrondissent vers l'infini négatif.
Divers
code
#
commentaire deLe
#
personnage commente tout jusqu'à la fin de la ligne.)
Utilisé pour terminer les blocs. Peut également être utilisé pour terminer l'ensemble du programme.
Tous les autres personnages sont ignorés.
la source
Calcul lambda binaire, 232 bits (29 octets)
0101000110100000000101011000000000011110000101111110011110000101110011110000001111000010110110111001111100001111100001011110100111010010110011100001101100001011111000011111000011100110111101111100111101110110000110010001101000011010
Voir http://en.wikipedia.org/wiki/Binary_lambda_calculus#Lambda_encoding pour plus de détails
la source
Je ne peux pas prendre le crédit pour celui-ci , mais j'ai pensé partager cet incroyable:
Brainf *** (423)
la source
BlockScript - 535
BlockScript est un langage trivial basé sur la pile de spaghetti que j'ai créé spécifiquement pour ce défi. L'interpréteur de base est blockscript.c .
Exemple de programme (imprime les 15 premiers numéros de Fibonacci):
L'interprète lit à la fois le code source et l'entrée du programme à partir de l'entrée standard, dans cet ordre. Cela signifie que pour exécuter un interpréteur au sein d'un interprète au sein d'un interprète, copiez et collez simplement:
Comme le film Inception , vous ne pouvez pas aller plus loin que trois niveaux. Ce n'est pas une question de temps, mais d'espace. BlockScript perd énormément de mémoire, et cela a à voir avec la façon dont le langage lui-même est conçu.
Référence du langage:
Obtenez l'interprète ici
Dans BlockScript, la «pile» n'est pas un tableau qui est écrasé par des opérations ultérieures comme vous en avez l'habitude. Il est en fait implémenté comme une liste liée immuable et une pile persiste pendant la durée du programme. De plus, aucun opérateur (sauf
@
) ne supprime les valeurs de la pile. Cependant, les modifications de pile n'affectent que le bloc dans lequel elles se produisent.Sélection de valeur
a
à traversz
Récupérez l'élément 0-25th de la pile et poussez-le dans la pile.
a
fait référence à la tête, ou au dernier élément poussé, de la pile.A
à traversZ
Récupérez le 0-25ème élément de l'image actuelle et poussez-le dans la pile.
[
Ouvrez un "cadre" pour sélectionner les éléments de la référence de pile (voir ci-dessous) sur la tête de la pile.
[
ne nécessite pas de correspondance]
, mais les cadres ont une portée lexicale. Dans BlockScript, la "portée" est déterminée par des accolades ({
...}
) qui forment des blocs. Ainsi, l'ouverture d'un cadre à l'intérieur d'un bloc n'aura aucun effet sur le code à l'extérieur du bloc.]
Fermez l'image actuelle, en revenant à l'image précédente (le cas échéant).
Blocs
{
...}
Créez un "bloc" et poussez-le dans la pile. À l'intérieur d'un bloc, la pile commencera à ce qu'elle était avant le bloc, sauf que la pile de l'appelant sera poussée en haut. Les piles sont persistantes et immuables dans BlockScript, donc les blocs sont des fermetures. L'idiome
{[
signifie ouvrir un bloc, puis ouvrir un cadre pour commencer à sélectionner des arguments (en utilisantA
throughZ
). La valeur de retour d'un bloc est la tête de la pile lorsqu'elle}
est atteinte.Exemple:
Cela imprime
123BCD123DCB123BCD123DCB…
. Les lettres minuscules font référence aux valeurs de la pile, tandis que les lettres majuscules font référence aux arguments (car le cadre est défini sur la pile de l'appelant).A!
prend la tête de l'appelant (qui est garanti d'être le bloc appelé) et l'appelle. Si vous vous demandez pourquoi il s'inverse àBCD
chaque fois, c'est parce qu'ilB. C. D.
pousse ces arguments dans l'ordre inverse juste avant que le bloc ne s'appelle.!
Appelez un bloc. Poussez la valeur de retour dans la pile.
Références de pile
&
Créez une référence de pile et poussez-la dans la pile. Considérez cela comme des «super-inconvénients», car il prend efficacement chaque élément de la pile et en forme un «tuple». L'idiome
&[
signifie que touta
,b
,c
appelés avant peut maintenant être consulté avecA
,B
,C
(pour le reste du bloc ou jusqu'à ce que]
l' on rencontre).En partie parce qu'il
&
capture plus de valeurs qu'il n'en a généralement besoin, BlockScript perd de la mémoire par conception.@
Basculez vers la pile pointée par la référence de pile
a
. Cet opérateur est plutôt bizarre, mais l'auto-interprète BlockScript l'utilise plusieurs fois pour éviter d'avoir à pousser deux fois les mêmes arguments. Les effets de@
(ou de toute opération de pile, d'ailleurs) sont limités au bloc dans lequel il est invoqué. De plus, le cadre n'est pas affecté par@
, donc le cadre peut être utilisé pour saisir les valeurs dont vous avez besoin après avoir changé de pile.Expression conditionnelle
?
<sur vrai>:
<sur faux>Expression conditionnelle, tout comme l'opérateur ternaire en C. Autrement dit, si
a
est "vrai" (c'est-à-dire différent de zéro entier), alors faites <sur vrai> , sinon faites <sur faux> .E / S
Remarque: L'entrée et la sortie se font en UTF-8. Un "caractère" est un entier correspondant à un index Unicode.
,
Obtenez le prochain caractère d'entrée et poussez-le dans la pile. Si la fin de l'entrée est atteinte, appuyez sur -1 à la place.
.
Sortez le personnage sur la tête de la pile.
Littéraux entiers / caractères
Remarque: les entiers et les caractères sont la même chose dans BlockScript.
'c
Poussez le caractère c.
[0-9] +
Appuyez sur un entier décimal.
Arithmétique
Ces opérateurs ne fonctionnent que sur des valeurs entières.
+
Calculerb
+a
(en poussant le résultat, mais sans ignorer aucune valeur).-
Calculerb
-a
.*
Calculerb
*a
./
Calculerb
/a
(division entière; arrondit vers l'infini négatif).%
Calculer leb
%a
(module entier; arrondi vers l'infini négatif).Opérateurs relationnels
Ces opérateurs ne fonctionnent que sur des valeurs entières.
<
Sib
est inférieur àa
, appuyez sur 1, sinon appuyez sur 0.>
=
Divers
#
Commentaire à la fin de la ligne;
la source
Zozotez LISP : 414
les sauts de ligne ajoutés pour obtenir un joli bloc ne sont pas nécessaires et ne sont pas comptés.
En théorie, il devrait être capable de s'exécuter lui-même, mais comme l'interpréteur d'origine est un binaire BrainFuck et lui-même un interprète, je n'ai pu tester que chaque partie. Une fois donné lui-même et une expression simple,
(p p)
je pense qu'il a besoin de plus de temps que les 40 minutes que j'ai attendu jusqu'à présent et j'utilise mon jeûnejitbf
pour l'exécuter qui (mal) utilise Perl Inline-C pour exécuter du code C à la volée.Il est impossible d'implémenter l'ensemble de Zozotez dans Zozotez car il n'a pas de moyen de muter contre et
:
(setq / define) en a besoin pour mettre à jour les liaisons. Je n'ai pas non plus implémenté d'argument explicite begin / progn ou & rest, des macros et des arguments d'impression spéciaux car je ne l'ai pas utilisé dans l'interpréteur. J'ai inclusp
(print) même si je ne l'utilise pas, les programmes doivent donc explicitement imprimer leurs calculs comme l'interpréteur d'origine.Le même non golfé:
la source
CHIQRSX9 + (probablement non concurrent), 2 octets
Il n'y a aucun moyen d'écrire un interpréteur auto-interprète dans ce langage basé sur HQ9 + sans utiliser
I
, qui exécute un interpréteur intégré qui traite STDIN.la source
eval
, qui est pour les expressions, pas pour les programmes.X
est censé rendre le langage Turing complet (donc capable de calculer des nombres premiers) d'une manière dépendante de l'implémentation.X
commande de l'interpréteur Perl perturbe aléatoirement le programme et l'exécute, ce qui signifie que l'on ne peut pas utiliser cette commande pour calculer de façon déterministe des nombres premiers. Pouvez-vous me donner un exemple d'interprète qui vous permet d'utiliserX
de la manière que vous avez spécifiée?Système de fichiers simultané Befunge 98 - 53 \ 18 octets (triche presque certainement)
Interprète complet de 53 octets sans restrictions (bien que je n'ai pas testé d'interactions de synchronisation compliquées impliquant le fractionnement et le conditionnement IP):
Lit l'entrée d'un fichier nommé
a
et l'exécute. Il n'est pas spécifié dans les règles que nous ne pouvons pas utiliser de code auto-modifiant.Interprète de 18 octets qui ne permet pas le wrapping (le déplacement IP d'un bord du code et en commençant par le bord opposé):
la source