Com base em um comentário de George Edison a essa pergunta , escreva o menor intérprete de auto-interpretação.
- Você pode usar o idioma de sua escolha.
- Idiomas vazios não contam. Seu programa deve ter pelo menos dois caracteres.
- O programa não precisa interpretar o idioma inteiro , apenas um subconjunto completo de recursos de idioma do Turing (que contém o intérprete).
- Quines não contam.
- Não use a função interna do seu idioma
eval
ou equivalente. O mesmo vale paraapply
etc.
code-golf
interpreter
Hoa Long Tam
fonte
fonte
/usr/bin/cat
) e quanto à integridade de Turing?sexp
analisador.Respostas:
CI - 260
320 → 260: Empurre mapeamentos simples de caractere para instrução e dobre-os. Isso reduz pela metade o tamanho do código por caso (há 18 casos), mas custa 30 caracteres para fazer a dobra.
Esta é outra das minhas linguagens construídas (intérprete base hospedado no Gist ). É único, pois o idioma reifica fragmentos de código. Ou seja, seqüências de instruções nessa linguagem baseada em pilha são usadas para o mesmo efeito que estruturas de dados ou fechamentos em outros idiomas:
O intérprete cria um fragmento de código de todo o programa antes de executá-lo, para que também possa ser considerado um compilador. Por esse motivo , empilhar o intérprete não resulta em sobrecarga exponencial do tempo de execução.
O intérprete deriva todos os seus operadores diretamente do intérprete host. No entanto, ele faz a análise por si só, portanto a maioria do código é apenas sequências que traduzem caracteres em seus respectivos literais de código. Isso não é o mesmo que usar
eval
, mas revela como qualquer implementação de linguagem de programação depende da semântica de sua linguagem / arquitetura host.Referência de idioma:
Obtenha o intérprete aqui
Blocos
(
...)
Crie um "bloco", que é efetivamente uma lista de instruções sem contexto. Internamente, pode até ser código de máquina.
quadra
$
Ligue para um bloco. O receptor recebe a pilha global, que inclui o bloco que está sendo chamado.
valor
^
Aumente um valor. Ou seja, transforme-o em um bloco que empurra esse valor.
Exemplo :
block1 block2
&
Una dois blocos, formando um que executa ambos em sequência.
Exemplo :
Manipulação de pilha
n
c
Copie o enésimo valor da pilha.
Exemplo :
n
p
Arranque o enésimo valor da pilha (remova-o e coloque-o na frente).
Exemplo :
n
d
Solte n valores da pilha.
0d
é um não-op.Exemplo :
Operadores relacionais
ab (on_true) (on_false)
=
Teste se a é igual a b. Consuma tudo, exceto o primeiro argumento, e chame on_true ou on_false. Se um argumento é zero e o outro é qualquer outro tipo, o resultado será falso. Caso contrário, aeb devem ser inteiros.
Exemplo :
ab (on_true) (on_false)
<
Teste se a é menor que b. aeb devem ser inteiros.
Exemplo :
ab (on_true) (on_false)
>
Teste se a é maior que b. aeb devem ser inteiros.
Exemplo :
um lo hi (on_true) (on_false)
~
Teste se lo <= a <= oi. a, lo e hi devem ser números inteiros.
Exemplo :
I / O
c
.
Coloque o caractere c (consumindo-o da pilha).
,
Pegue um personagem e empurre-o para a pilha. Se o final do arquivo foi atingido, -1 é pressionado.
c
!
Desmarque um personagem. Assim como ungetc em C, apenas uma resposta é permitida.
Literais inteiros
'c
Empurre o caractere c.
[0-9] +
Empurre um número inteiro decimal.
Aritmética
+
-
ab
*
Adicione / subtraia / multiplique dois números.
Exemplo :
ab
/
ab
%
Divisão e módulo. Ao contrário de C, eles se aproximam do infinito negativo.
Diversos
#
comentário de códigoO
#
personagem comenta tudo até o final da linha.)
Usado para finalizar blocos. Também pode ser usado para finalizar o programa inteiro.
Todos os outros caracteres são ignorados.
fonte
Cálculo binário lambda, 232 bits (29 bytes)
0101000110100000000101011000000000011110000101111110011110000101110011110000001111000010110110111001111100001111100001011110100111010010110011100001101100001011111000011111000011100110111101111100111101110110000110010001101000011010
Veja http://en.wikipedia.org/wiki/Binary_lambda_calculus#Lambda_encoding para obter detalhes
fonte
Não posso me responsabilizar por este , mas pensei em compartilhar este incrível:
Brainf *** (423)
fonte
BlockScript - 535
O BlockScript é uma linguagem trivial baseada em pilha de espaguetes que criei especificamente para esse desafio. O intérprete de base é blockscript.c .
Programa de amostra (imprime os 15 primeiros números de Fibonacci):
O intérprete lê o código fonte e a entrada do programa a partir da entrada padrão, nessa ordem. Isso significa que, para executar um intérprete dentro de um intérprete, copie e cole:
Como o filme Inception , você praticamente não pode ir além de três níveis. Não é uma questão de tempo, mas de espaço. O BlockScript vaza memória profusamente, e isso tem a ver com a forma como a própria linguagem é projetada.
Referência de idioma:
Obtenha o intérprete aqui
No BlockScript, a "pilha" não é uma matriz que é substituída por operações subseqüentes como você pode estar acostumado. Na verdade, é implementado como uma lista vinculada imutável e uma pilha persiste durante o programa. Além disso, nenhum operador (exceto
@
) remove valores da pilha. No entanto, as modificações da pilha afetam apenas o bloco em que ocorrem.Seleção de valor
a
atravész
Busque o item 0-25º da pilha e empurre-o para a pilha.
a
refere-se ao cabeçalho, ou item empurrado mais recentemente, da pilha.A
atravésZ
Busque o item 0-25º do quadro atual e empurre-o para a pilha.
[
Abra um "quadro" para selecionar itens da referência da pilha (veja abaixo) no cabeçalho da pilha.
[
não exige uma correspondência]
, mas os quadros têm escopo lexicamente. No BlockScript, "escopo" é determinado por chaves ({
...}
) que formam blocos. Assim, abrir um quadro dentro de um bloco não terá efeito no código fora do bloco.]
Feche o quadro atual, retornando ao quadro anterior (se houver).
Blocos
{
...}
Crie um "bloco" e empurre-o para a pilha. Dentro de um bloco, a pilha começará do que era antes do bloco, exceto que a pilha do chamador será empurrada para cima. As pilhas são persistentes e imutáveis no BlockScript, portanto, os blocos são encerramentos. O idioma
{[
significa abrir um bloco e, em seguida, abrir um quadro para começar a selecionar argumentos (usandoA
atravésZ
). O valor de retorno de um bloco é o cabeçalho da pilha quando}
é atingido.Exemplo:
Isso imprime
123BCD123DCB123BCD123DCB…
. As letras minúsculas se referem aos valores da pilha, enquanto as letras maiúsculas se referem aos argumentos (porque o quadro está definido como a pilha do chamador).A!
pega o chefe do chamador (que é garantidamente o bloco que está sendo chamado) e o chama. Se você está se perguntando por que ele reverteBCD
todas as vezes, é porqueB. C. D.
envia esses argumentos na ordem inversa antes do bloco se chamar.!
Ligue para um bloco. Empurre o valor de retorno para a pilha.
Referências de pilha
&
Crie uma referência de pilha e empurre-a para a pilha. Pense nisso como "superconvenientes", pois efetivamente pega todos os itens da pilha e forma uma "tupla". O idioma
&[
significa que tudoa
,b
,c
referidas antes de agora pode ser acessado comA
,B
,C
(para o restante do bloco ou até que]
seja encontrado).Em parte porque
&
captura mais valores do que normalmente precisa, o BlockScript vaza memória por design.@
Alterne para a pilha apontada pela referência da pilha
a
. Esse operador é um pouco estranho, mas o auto-intérprete BlockScript o usa algumas vezes para evitar ter que empurrar os mesmos argumentos duas vezes. Os efeitos de@
(ou qualquer operação de pilha, nesse caso) são limitados ao bloco em que é invocado. Além disso, o quadro não é afetado@
, portanto, o quadro pode ser usado para obter os valores necessários após a troca de pilhas.Expressão condicional
?
<em verdadeiro>:
<em falso>Expressão condicional, assim como o operador ternário em C. Ou seja, se
a
for "true" (ou seja, não for igual ao número inteiro zero), faça <em true> , caso contrário <em false> .I / O
Nota: A entrada e a saída são feitas em UTF-8. Um "caractere" é um número inteiro correspondente a um índice Unicode.
,
Obtenha o próximo caractere de entrada e empurre-o para a pilha. Se o final da entrada for alcançado, pressione -1 em vez disso.
.
Coloque o caractere na cabeça da pilha.
Literais de número inteiro / caractere
Nota: Inteiros e caracteres são a mesma coisa no BlockScript.
'c
Empurre o caractere c.
[0-9] +
Empurre um número inteiro decimal.
Aritmética
Esses operadores trabalham apenas em valores inteiros.
+
Calculeb
+a
(pressionando o resultado, mas não descartando nenhum valor).-
Computarb
-a
.*
Computarb
*a
./
Computarb
/a
(divisão inteira; arredonda para o infinito negativo).%
Calculeb
%a
(módulo inteiro; arredonda para o infinito negativo).Operadores relacionais
Esses operadores trabalham apenas em valores inteiros.
<
Seb
for menor quea
, pressione 1, depois pressione 0.>
=
Diversos
#
Comentar até o final da linha;
fonte
Zozotez LISP : 414
linefeeds adicionados para obter um bom bloco não são necessários e não são contados.
Em teoria, ele deve ser capaz de rodar sozinho, mas como o intérprete original é um binário do BrainFuck e é um intérprete, só consegui testar cada parte. Quando atribuída a si mesma e a uma expressão simples
(p p)
, acho que precisa de mais tempo do que os 40 minutos que esperei até agora e estou usando o meu rápidojitbf
para executá-lo, que (mis) usa o Perl Inline-C para executar o código C em tempo real.É impossível implementar o Zozotez inteiro no Zozotez, pois ele não tem meios de alterar contras e
:
(setq / define) precisa disso para atualizar as ligações. Também não implementei argumentos explícitos de start / progn ou & rest, macros e argumentos especiais de impressão, pois não o usei no intérprete. Incluíp
(imprimi) mesmo que não o use, para que os programas precisem imprimir explicitamente seus cálculos, assim como o intérprete original.O mesmo não destruído:
fonte
CHIQRSX9 + (provavelmente não concorrente), 2 bytes
Não há como escrever um intérprete de auto-interpretação nesta linguagem baseada no HQ9 + sem o uso
I
, que executa um intérprete interno que processa STDIN.fonte
eval
, que é para expressões, não para programas.X
deve tornar a linguagem Turing completa (portanto, capaz de calcular primos) de uma maneira dependente da implementação.X
comando do interpretador Perl aleatoriamente perturba o programa e o executa, o que significa que não se pode usar senão o comando para calcular deterministicamente números primos. Você pode me dar um exemplo de intérprete que permita usarX
da maneira especificada?Sistema de arquivos simultâneo Befunge 98 - 53 \ 18 bytes (quase certamente trapaceando)
Intérprete completo de 53 bytes sem restrições (embora eu não tenha testado interações de tempo complicadas que envolvem divisão e quebra de IP):
Lê a entrada de um arquivo chamado
a
e a executa. Não está especificado nas regras que não podemos usar código auto-modificável.Intérprete de 18 bytes que não permite quebra automática (o movimento do IP de uma borda do código e a partir da borda oposta):
fonte