Kendinden Tercüman Tercüman


25

George Edison'un bu soruya yaptığı bir yorumdan yola çıkarak, en küçük öz tercüman tercümanını yaz.

  • Seçtiğiniz dili kullanabilirsiniz.
  • Boş diller sayılmaz. Programınız en az iki karakter uzunluğunda olmalı.
  • Programın tüm dili yorumlaması gerekmez , sadece bir Turing tamamlayıcı dil özelliği alt kümesi (tercümanı içeren).
  • Quines sayılmaz.
  • Dilinizin yerleşik evalişlevini veya eşdeğerini kullanmayın. Aynı şey applyvb. İçin de geçerlidir.

1
(Hmm .. Bir şey yapmalıyım /usr/bin/cat) peki Turing-eksiksizliği?
Ming-Tang,

@ SHiNKiROU: Teşekkürler, bunu bir test olarak düşünmedim. Güncellenmiş.
Hoa Long Tam

İlgili: Dil , Yığın Taşması üzerine kendi içinde yazılmış en küçük tercüman olmasına rağmen, burada verilen kurallara uyan az (sadece bir?) Cevaptır.
dmckee

1
Scheme sexp ayrıştırıcısını yeniden mi yazmalıyız, yoksa ana dilin tamam olduğunu düşünebilir miyiz?
JB,

@JB: Dilin dize işleme yardımcı programları, sexpayrıştırıcı dahil, iyi durumdadır .
Hoa Long Tam

Yanıtlar:


19

CI - 260

,(1p0(2d())(41(2d())('#((1p0()(10()(1d,1p$)=)<)$2d,1p$)(40(1d,1c$^)(''(1d,^)('0
'9('0-(,'0'9('0-2p10*+1p$)(!1d)~)$^)(0($)'$(^)'^(&)'&(c)'c(p)'p(d)'d(=)'=(<)'<(
>)'>(~)'~(.)'.(,)',(!)'!(+)'+(-)'-(*)'*(/)'/(%)'%()38p(1p3p0(3d)((2)(3)=p1d1p$)
=)$)~)=)=,2p$&)=)=)<)$$

320 → 260: Basit karakter-talimat eşlemelerini itin, sonra üzerine katlayın. Bu, vaka başına kod boyutunu yarıya indirir (18 durum vardır), ancak katlamayı yapmak 30 karaktere mal olur.

Bu benim yerleşik dillerimden bir diğeridir ( Gist'te barındırılan temel tercüman ). Dilin kod parçalarını yeniden düzenlemesi benzersiz. Diğer bir deyişle, bu yığın tabanlı dildeki komut dizileri, diğer dillerde veri yapıları veya kapatmalarıyla aynı etkiye sahiptir:

1^      # Push a 1, and "lift" it to be a code literal.
(5 +)   # Define a code literal.
&       # Join the two code literals, forming (1 5 +)
$       # Execute the code literal.

Tercüman, çalıştırmadan önce tüm programın bir kod parçasını oluşturur, böylece bir derleyici olarak da değerlendirilebilir. Bu nedenle , tercümanın istiflenmesi, üssel çalışma zamanı ek yükü ile sonuçlanmaz.

Tercüman, tüm operatörlerini doğrudan ana tercümandan türetir. Ancak, ayrıştırmayı kendi başına yapar, bu nedenle kodun çoğu sadece karakterleri kendi kod hazırlayıcılarına çeviren dizilerdir. Bu kullanmakla aynı değildir eval, ancak herhangi bir programlama dili uygulamasının ana dilin / mimarinin anlamına ne kadar bağımlı olduğunu ortaya koymaktadır.


Dil referansı:

Tercümanı buraya getir

Bloklar

  • ( ... )

    Etkili bağlamda olmayan bir talimatlar listesi olan bir "blok" oluşturun. Dahili olarak, makine kodu bile olabilirdi.

  • blok $

    Bir blok çağır. Callee, çağrılan bloğu içeren global yığına verilir.

  • değer ^

    Bir değer kaldırın. Yani, bu değeri iten bir bloğa çevirin.

    Örnek :

       1 ^
    == (1)
    
  • blok1 blok2 &

    İki bloğu birleştirin, her ikisini de sırayla yürüten birini oluşturun.

    Örnek :

       (1) (2) &
    == (1 2)
    

Yığın manipülasyonu

  • n c

    Yığının nth değerini kopyalayın.

    Örnek :

       5 4 3 2 1 0 3c
    == 5 4 3 2 1 0 3
    
  • n p

    Yığının nth değerini toplayın (çıkarın ve öne getirin).

    Örnek :

       5 4 3 2 1 0 3p
    == 5 4 2 1 0 3
    
  • n d

    Yığından n değerini düşür. 0dbir ameliyat değildir.

    Örnek :

       5 4 3 2 1 0 3d
    == 5 4 3
    

İlişkisel operatörler

  • ab (on_true) (on_false) =

    Eşit olup olmadığını test edin b. İlk argüman hariç hepsini tüketin ve on_true veya on_false arayın. Bir argüman sıfır, diğeri herhangi bir tür ise sonuç yanlış olur. Aksi takdirde, a ve b tamsayıları olmalıdır.

    Örnek :

       3 3 ('0+ .) (1d) =
    == 3 '0+ .
    
  • ab (on_true) (on_false) <

    A'nın b'den az olup olmadığını test edin. a ve b tamsayı olmalıdır.

    Örnek :

       3 5 (1d 5) () <
    == 3 1d 5
    == 5
    
  • ab (on_true) (on_false) >

    A'nın b'den büyük olup olmadığını test edin. a ve b tamsayı olmalıdır.

    Örnek :

       3 5 (1d 5) () >
    == 3
    
  • a lo hi (on_true) (on_false) ~

    Lo <= a <= hi ise test edin. a, lo ve merhaba tamsayılar olmalıdır.

    Örnek :

       3 0 10 ('0+ .) (1d) ~
    == 3 '0+ .
    

I / O

  • c .

    C karakterini (yığından tüketerek) koyun.

  • ,

    Bir karakter bulun ve yığına itin. Dosyanın sonuna gelindiğinde, -1 tuşuna basılır.

  • c !

    Bir karakteri aç. Tıpkı C'deki ungetc gibi, yalnızca bir geri çekmeye izin verilir.

Tamsayı değişmezleri

  • 'c

    Karakter c itin.

  • [0-9] +

    Ondalık bir tamsayı itin.

Aritmetik

  • ab +
  • ab -
  • ab *

    İki sayı ekle / çıkar / çarp.

    Örnek :

       3 5 + 7 3 + *
    == 80
    
  • ab /

  • ab %

    Bölünme ve modül. C'den farklı olarak, bu tur negatif sonsuzluğa doğru.

Çeşitli

  • kod #yorumu

    #Karakter satırının sonuna her şeyi yorumlar.

  • )

    Blokları sonlandırmak için kullanılır. Tüm programı sonlandırmak için de kullanılabilir.

  • Diğer tüm karakterler göz ardı edilir.


24

İkili Lambda Hesabı, 232 bit (29 bayt)

0101000110100000000101011000000000011110000101111110011110000101110011110000001111000010110110111001111100001111100001011110100111010010110011100001101100001011111000011111000011100110111101111100111101110110000110010001101000011010

Ayrıntılar için http://en.wikipedia.org/wiki/Binary_lambda_calculus#Lambda_encoding adresine bakın.


2
Bu neden kabul görmedi cevap D: BLC harika!
kedi,

Bunu açıklayabilir misin?
PyRulez

1
Ne yazık ki, Wikipedia Binary Lambda Calculus sayfasını kaldırdı. Benim tromp.github.io/cl/cl.html I korunmuş kopyasına ve bir kağıda sayfa bağlantıları tercüman işleyişini açıklayan yazdı.
John Tromp

13

Bunun için kredi alamam, ama bu muhteşem olanı paylaşacağımı düşündüm:

Brainf *** (423)

>>>+[[-]>>[-]++>+>+++++++[<++++>>++<-]++>>+>+>+++++[>++>++++++<<-]+>>>,<++[[>[
->>]<[>>]<<-]<[<]<+>>[>]>[<+>-[[<+>-]>]<[[[-]<]++<-[<+++++++++>[<->-]>>]>>]]<<
]<]<[[<]>[[>]>>[>>]+[<<]<[<]<+>>-]>[>]+[->>]<<<<[[<<]<[<]+<<[+>+<<-[>-->+<<-[>
+<[>>+<<-]]]>[<+>-]<]++>>-->[>]>>[>>]]<<[>>+<[[<]<]>[[<<]<[<]+[-<+>>-[<<+>++>-
[<->[<<+>>-]]]<[>+<-]>]>[>]>]>[>>]>>]<<[>>+>>+>>]<<[->>>>>>>>]<<[>.>>>>>>>]<<[
>->>>>>]<<[>,>>>]<<[>+>]<<[+<<]<]

10

BlockScript - 535

{[B':=?0:B';=?0:B'}=?0:B'{=?,A!,A!d1c&:B'?=?,A!,A!2e&:B''=?,,A!d3c&:B{[B'0<?0:B
'9>?0:1}!?B'0-{[,g!?c'0-B10*d+A!:Bd]A!d3c&}!:B'#=?{[,10=?,]A!:A!}!:,A!Bb&}{[AC[
B]DB?[AB{[Bh&hbhn!}{[B[AB]C?1-eA!:b}&[C1=?E[C]FHc&B!:C2=?{G?D:E[C}!FHcI!:C3=?E[
C]B!:C'!=?G[ABC]Hc&dbh&D?b@I!B!:b@I!:C'&=?HB!:C'@=?FGDI!:C'[=?GF&HDI!:C']=?F[A]
HDI!:C',=?,B!:C'.=?G.FHDI!:C'a'z{[DC<?0:DB>?0:1}!?Ce-HA!B!:C'A'Ze!?F[B]Cg-dA!B!
:{C'+=?{[CB+}:C'-=?{[CB-}:C'*=?{[CB*}:C'/=?{[CB/}:C'%=?{[CB%}:C'<=?{[CB<}:C'>=?
{[CB>}:C'==?{[CB=}:0}!?H[A][B]Ge!B!:FHDI!:c},c!0ac&0&0&0bho!;

BlockScript, özellikle bu zorluk için yarattığım önemsiz bir spagetti yığını tabanlı dildir. Temel tercüman blockscript.c'dir .

Örnek program (ilk 15 Fibonacci numarasını yazdırır):

{[B?B10/A!B10%d&:0}
{[B0<?'-.0B-A!:{B?Bh!{[B?B[A]A!B[B]'0+.:}!:'0.}!10.}
{[B?Dd!DC+B1-CecA!:}
0 1 15d!
;

Tercüman, hem kaynak kodu hem de program girişini bu sırada standart girdiden okur. Bu, bir tercüman içinde bir tercüman içinde bir tercüman çalıştırmak, sadece kopyalayıp yapıştırmak anlamına gelir:

# Level 1
{[B':=?0:B';=?0:B'}=?0:B'{=?,A!,A!d1c&:B'?=?,A!,A!2e&:B''=?,,A!d3c&:B{[B'0<?0:B
'9>?0:1}!?B'0-{[,g!?c'0-B10*d+A!:Bd]A!d3c&}!:B'#=?{[,10=?,]A!:A!}!:,A!Bb&}{[AC[
B]DB?[AB{[Bh&hbhn!}{[B[AB]C?1-eA!:b}&[C1=?E[C]FHc&B!:C2=?{G?D:E[C}!FHcI!:C3=?E[
C]B!:C'!=?G[ABC]Hc&dbh&D?b@I!B!:b@I!:C'&=?HB!:C'@=?FGDI!:C'[=?GF&HDI!:C']=?F[A]
HDI!:C',=?,B!:C'.=?G.FHDI!:C'a'z{[DC<?0:DB>?0:1}!?Ce-HA!B!:C'A'Ze!?F[B]Cg-dA!B!
:{C'+=?{[CB+}:C'-=?{[CB-}:C'*=?{[CB*}:C'/=?{[CB/}:C'%=?{[CB%}:C'<=?{[CB<}:C'>=?
{[CB>}:C'==?{[CB=}:0}!?H[A][B]Ge!B!:FHDI!:c},c!0ac&0&0&0bho!;

# Level 2
{[B':=?0:B';=?0:B'}=?0:B'{=?,A!,A!d1c&:B'?=?,A!,A!2e&:B''=?,,A!d3c&:B{[B'0<?0:B
'9>?0:1}!?B'0-{[,g!?c'0-B10*d+A!:Bd]A!d3c&}!:B'#=?{[,10=?,]A!:A!}!:,A!Bb&}{[AC[
B]DB?[AB{[Bh&hbhn!}{[B[AB]C?1-eA!:b}&[C1=?E[C]FHc&B!:C2=?{G?D:E[C}!FHcI!:C3=?E[
C]B!:C'!=?G[ABC]Hc&dbh&D?b@I!B!:b@I!:C'&=?HB!:C'@=?FGDI!:C'[=?GF&HDI!:C']=?F[A]
HDI!:C',=?,B!:C'.=?G.FHDI!:C'a'z{[DC<?0:DB>?0:1}!?Ce-HA!B!:C'A'Ze!?F[B]Cg-dA!B!
:{C'+=?{[CB+}:C'-=?{[CB-}:C'*=?{[CB*}:C'/=?{[CB/}:C'%=?{[CB%}:C'<=?{[CB<}:C'>=?
{[CB>}:C'==?{[CB=}:0}!?H[A][B]Ge!B!:FHDI!:c},c!0ac&0&0&0bho!;

# Level 3
{[B?B10/A!B10%d&:0}
{[B0<?'-.0B-A!:{B?Bh!{[B?B[A]A!B[B]'0+.:}!:'0.}!10.}
{[B?Dd!DC+B1-CecA!:}
0 1 15d!
;

Inception filmi gibi, üç seviyeden daha derine inemezsiniz. Bu zaman meselesi değil, mekan. BlockScript, belleği bolca sızdırıyor ve bunun dilin kendisinin nasıl tasarlandığı ile ilgili.


Dil referansı:

Tercümanı buraya getir

BlockScript'te "yığın", alıştığınız gibi sonraki işlemler tarafından üzerine yazılmış bir dizi değildir. Aslında değişmez bir bağlantılı liste olarak uygulanır ve program süresince bir yığın devam eder. Ayrıca, operatör yok (hariç@ ) yığıntan değerleri kaldırmaz. Ancak, yığın değişiklikleri yalnızca içinde bulundukları bloğu etkiler.

Değer seçimi

  • a vasitasiyla z

    0-25. Öğeyi yığından alın ve yığına itin. ayığının başını veya en yakın zamanda basılan öğesini ifade eder.

  • A vasitasiyla Z

    Geçerli karenin 0-25'inci öğesini alın ve yığına itin.

  • [

    Yığın başındaki yığın referansından (aşağıya bakın) öğeler seçmek için bir "çerçeve" açın. [eşleştirme gerektirmez ], ancak çerçeveler sözcüksel olarak kapsamlıdır. BlockScript'te "kapsam", blokları oluşturan parantezlerle ( {... }) belirlenir . Bu nedenle, bir bloğun içindeki bir çerçevenin açılması, bloğun dışındaki kod üzerinde etkili olmayacaktır.

  • ]

    Mevcut kareyi kapatın, önceki kareye dönün (varsa).

Bloklar

  • { ... }

    Bir "blok" oluşturun ve yığına itin. Bir bloğun içinde istif, istifin üst kısmına itilmesi dışında, bloktan önce olduğu gibi başlayacaktır. Yığınlar BlockScript'te kalıcı ve değişmez olduğundan bloklar kapanır. Deyim {[araçlar daha sonra (kullanarak argüman seçmeye bir çerçeve açılır, bir blok açık Ayoluyla Z). Bir bloğun dönüş değeri }, ulaşıldığında yığının başıdır .

    Örnek:

    '3 '2 '1 {[ b. d. f. B. C. D. A! } 'D 'C 'B d!;
    

    Bu yazdırır 123BCD123DCB123BCD123DCB…. Küçük harfler yığın değerlerine, büyük harfler ise argümanlara atıfta bulunur (kare arayanın yığınına ayarlandığı için). A!Arayan kişinin kafasını alır (bu, aranan blok olduğu garanti edilir) ve onu çağırır. Neden BCDher seferinde neden tersine döndüğünü merak ediyorsanız , B. C. D.bu argümanları blok kendini çağırmadan hemen önce ters sırada iter.

  • !

    Bir blok çağır. Dönüş değerini yığına itin.

Yığın referansları

  • &

    Bir yığın referansı oluşturun ve yığına itin. Bunu, "süper-eksileri" olarak düşünün, çünkü yığıntaki her öğeyi etkin bir şekilde alır ve bunun dışında bir "demet" oluşturur. Deyim &[ne olursa olsun bu araçlar a, b, cartık ile erişilebilir önce de ifade A, B, C(blok ya kadar geri kalan kısmı için] karşılaşılmaktadır).

    Kısmen &, genellikle ihtiyaç duyduğundan daha fazla değer yakaladığı için, BlockScript tasarım gereği bellek sızdırıyor.

  • @

    Yığın referansının gösterdiği yığına geçin a. Bu operatör oldukça garip, ancak BlockScript kendini yorumlayıcı, aynı argümanları iki kez zorlamak zorunda kalmamak için birkaç kez kullanıyor. Bu konuda @(veya herhangi bir istif işleminin) etkileri, çağrıldığı blokla sınırlıdır. Ayrıca, çerçeve bundan etkilenmez @, bu nedenle çerçeve yığınları değiştirdikten sonra ihtiyaç duyduğunuz değerleri almak için kullanılabilir.

Koşullu ifade

  • ? <on true> : <yanlış>

    Koşullu ifade, tıpkı C'deki üçlü operatör gibi, ayani "true" ise (yani, tamsayıya eşit değil), o zaman <true> yapın , aksi takdirde <false> yapın .

I / O

Not: Giriş ve çıkış UTF-8'de yapılır. Bir "karakter" bir Unicode indeksine karşılık gelen bir tamsayıdır.

  • ,

    Bir sonraki giriş karakterini alın ve yığına itin. Giriş sonuna ulaşıldığında, yerine -1 tuşuna basın.

  • .

    Yığının başındaki karakteri çıkar.

Tamsayı / karakter değişmezleri

Not: Tamburlar ve karakterler BlockScript'te aynı şeydir.

  • 'c

    Karakter c itin.

  • [0-9] +

    Ondalık bir tamsayı itin.

Aritmetik

Bu operatörler sadece tamsayı değerleri üzerinde çalışır.

  • +Hesapla b+ a(sonucu bastır, ancak her iki değeri de atma).
  • -Hesapla b- a.
  • *Hesapla b* a.
  • /Hesapla b/ a(tam sayı bölümü; negatif sonsuzluğa yuvarlar).
  • %b% Hesaplayın a(tamsayı modülü; negatif sonsuzluğa yuvarlar).

İlişkisel operatörler

Bu operatörler sadece tamsayı değerleri üzerinde çalışır.

  • <Eğer bdaha az olduğu aitme 1, başka itme 0,.
  • >
  • =

Çeşitli

  • # Satırın sonuna kadar yorum yapın
  • Program bitmeli ;
  • Diğer tüm karakterler göz ardı edilir.

2
İsa. CI için yaptığınız gibi özellikleri paylaşmak ister misiniz?
Casey,

@Casey: Bir referans eklendi.
Joey Adams

1
Hayal kurduğunu bilmek ister misin? ... Seviye 4.
Mateen Ulhaq

3

Zozotez LISP : 414

güzel bir blok elde etmek için eklenen satır beslemelerine ihtiyaç duyulmaz ve sayılmaz.

((\(E V A L)(E(r)'(())))(\(x e)(?(s x)(V x e)((\(b j)(?(= b ")(a j)(?(= b \)x
(?(= b ?)(?(E(a j)e)(E(a(d j))e)(E(a(d(d j)))e))(?(s b)(A b(E(a j)e)(E(a(d j)
)e))(E(a(d(d b)))(L(a(d b))j e)))))))(E(a x)e)(d x))))(\(x g)(? g(?(= x(a(a
g)))(d(a g))(V x(d g)))x))(\(f h v)(?(= f r)(r)(?(= f p)(p h)(?(= f s)(s h)(?
(= f a)(a h)(?(= f d)(d h)(?(= f =)(= h v)(c h v))))))))(\(k v i)(? k(L(d k)(
d v)(c(c(a k)(E(a v)i))i))i)))

Teoride kendini çalıştırabilmeli, ancak orijinal tercüman bir BrainFuck ikilisi ve kendisi de bir tercüman olduğu için sadece her bir parçayı test edebildim. Kendisi ve basit bir ifade verildiğinde (p p), şu ana kadar beklediğim 40 dakikadan daha fazla zamana ihtiyaç duyduğunu düşünüyorum ve jitbfçalıştırmak için oruç tutuyorum (hangi yanlış) anında C kodunu çalıştırmak için Perl Inline-C kullanıyor.

Tüm Zozotez'i Zozotez'de uygulamak mümkün değildir çünkü mutasyona uğratma aracına sahip değildir ve :(setq / define) bağları güncellemek için buna ihtiyaç duymaktadır. Ayrıca tercüman içinde kullanmadığım için açık bir başlangıç ​​/ progn ya da & rest argümanı, makrolar ve özel yazdırma argümanları uygulamadım. Dahil ettimp (yazdır), böylece programların hesaplarını orijinal çevirmen gibi açıkça yazdırmaları gerekir.

Aynı ungolfed:

;; A stand alone Zozotez script need to be
;; contained in one expression, here with
;; all functions provided as arguments to
;; get them bound in the dynamic environment
((\ (E V A L)
  (E(r)'(())))
 ;; E (EVAL)
 (\ (x e)
   (? (s x)
      (V x e)
      ((\ (b j)
         (? (= b ") (a j)
         (? (= b \) x
         (? (= b ?) (? (E(a j)e) (E(a(d j))e) (E(a(d(d j)))e))
         (? (s b)
            (A b (E(a j)e) (E (a(d j))e))
            (E (a(d(d b))) (L(a(d b))j e)))))))
       (E (a x) e)(d x))))
 ;; V (VALUE / symbol->value)
 (\ (x g)
   (? g
      (? (= x (a (a g)))
         (d (a g))
         (V x (d g)))
      x))
 ;; A (APPLY) but just for primitives
 (\ (f h v)
   (? (= f r) (r)
   (? (= f p) (p h)
   (? (= f s) (s h)
   (? (= f a) (a h)
   (? (= f d) (d h)
   (? (= f =)
      (= h v)
      (c h v))))))))
 ;; L ( joint evLis / extend-env)
 (\ (k v i)
   (? k
      (L (d k) 
         (d v)
     (c (c (a k) 
           (E (a v) i)) 
        i))
      i)))

0

CHIQRSX9 + (muhtemelen rekabet etmeyen), 2 bayt

+I

Bu HQ9 + tabanlı dilde I, STDIN'i işleyen yerleşik bir tercüman çalıştıran kendi kendine çeviren bir tercüman yazmanın bir yolu yoktur .


1
Kuralların hiçbir yerinde, yerleşik kendi kendine tercümanlara izin verilmediği söylenemez. evalİfadeler için olan programları değil diyor .
Outgolfer Erik,

Bir hesaplama bu dilde nasıl hazırlanır?
pppery

@ppperry'nin XTuring-tamamlayıcı (bu nedenle, primerleri hesaplayabilen) dili uygulamaya bağlı bir şekilde yapması beklenir.
user8397947,

Esolang sayfasına bakıldığında, Perl yorumlayıcısının Xkomutu rastgele bir şekilde programı bozar ve onu çalıştırır; XBelirttiğiniz şekilde kullanmanıza izin veren örnek bir tercüman verebilir misiniz ?
pppery

@ppperry Anlaşılan Perl'de yazılmış tercüman tek tercüman, yani hayır. Ayrıca, belirli bir değerle "randomize" olduğunda primeları hesaplayan bir program varsa ne olur?
user8397947,

0

Eşzamanlı Dosya Sistemi Befunge 98 - 53 \ 18 bayt (neredeyse kesinlikle hile)

Kısıtlama olmadan tam 53 bayt tercüman (IP ayırma ve sarma içeren karmaşık zamanlama etkileşimlerini test etmemiş olmama rağmen):

v ;;;;;;;;
>]390'ai@
 t;;;;;;;;
;>zzzzz#;

Adındaki bir dosyadan girdi okur ave onu yürütür. Kurallarda, kendi kendini değiştiren kodu kullanamayacağımız belirtilmemiştir.

Kaydırmaya izin vermeyen 18 bayt tercüman (IP, kodun bir kenarının hareket etmesi ve karşı kenardan başlaması):

]210'ai@
t
><
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.