Tercüman makine kodu üretiyor mu?


42

Derleyici ve tercüman konularını yoğun olarak çalışıyorum. Temel anlayışımın doğru olup olmadığını kontrol etmek istiyorum, öyleyse şunu kabul edelim:

"Foobish" adında bir dilim var ve anahtar kelimeleri

<OUTPUT> 'TEXT', <Number_of_Repeats>;

Yani konsola 10 defa yazdırmak istersem, yazarım

OUTPUT 'Hello World', 10;

Merhaba World.foobish dosyası.

Şimdi kendi seçimim olan bir tercüman yazıyorum - bu durumda C #:

using System;

namespace FoobishInterpreter
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            analyseAndTokenize(Hello World.foobish-file)//Pseudocode
            int repeats = Token[1];
            string outputString = Token[0];
            for (var i = 0; i < repeats; i++)
            {
                Console.WriteLine(outputString);
            }
        }
    }
}

Çok kolay bir tercüman düzeyinde, tercüman senaryo dosyasını, vb. Analiz eder ve foobish dilini tercümanın uygulanmasında uygular.

Bir derleyici doğrudan fiziksel donanımda çalışan bir makine dili oluşturur mu?

Yani bir tercüman makine dili üretmez, fakat bir derleyici girişi için yapar mı?

Derleyicilerin ve tercümanların nasıl çalıştığı ile ilgili temel yanlış anlamalar var mı?


21
Sizce C # "derleyici" ne yapar? Bir ipucu olarak, gelmez makine kodu üretir.
Philip Kendall

3
Bir Java derleyicisi JVM için kod üretir. Dolayısıyla bir derleyicinin hedef makinesi, doğrudan donanım tarafından çalıştırılmayan sanal bir makine olabilir. Tercüman ve derleyici arasındaki temel fark, derleyici ilk önce tüm kaynak kodunu kontrol eder ve hedef makine diline çevirir. Bu derlenmiş kod daha sonra amaçlandığı makine tarafından yürütülür. Öte yandan, bir tercüman programınızın parçalarını anında çevirir ve uygular.
Giorgio

@ Giorgio: Bir JIT gibi mi demek istiyorsun?
Robert Harvey,

2
@RobertHarvey: Java Derleyicisini (javac) kastettim: JVM için bytecode ürettiğini bildiğim kadarıyla. Ve, yine AFAIK, daha sonra JIT (çalışma zamanında) çok sık kullanılan yerel makine diline bir bytecode derler.
Giorgio

4
bir derleyici çeviri demektir. Her türlü dili yayabilir: c, montaj, javascript, makine kodu.
Esben Skov Pedersen

Yanıtlar:


77

"Tercüman" ve "derleyici" terimleri eskisinden çok daha bulanık. Yıllar önce, derleyicilerin daha sonra çalıştırılacak olan makine kodunu üretmeleri daha yaygındı, yorumlayıcılar ise doğrudan kaynak kodunu "daha az ya da çok" çalıştırdı ". Böylece bu iki terim daha önce anlaşıldı.

Ancak bugün “derleyici” ve “tercüman” kullanımında birçok değişiklik vardır. Örneğin, VB6 bayt kodunu "bir Ara Dil" biçiminde "derler" , sonra VB Çalışma Zamanı Modülü tarafından "yorumlanır". Benzer bir işlem , eski günlerde tercüman olarak düşünülebilecek olan Just-In-Time Compiler (JIT) tarafından yürütülen CIL'yi üreten C # 'de gerçekleşir . JIT'in çıktısını , eski günlerde bir derleyicinin sonucu olan NGen.exe aracını kullanarak gerçek bir ikili dosyada "dondurarak kurutabilirsiniz" .

Yani sorunuzun cevabı neredeyse eskisi kadar kolay değil.

Wikipedia'da Çevirmenlere Karşı Diğer Okuma
Derleyicileri


6
@Giorgio: Günümüzde çoğu tercüman aslında kaynak kodunu yerine getirmiyor, bunun yerine bir AST çıktısı veya benzer bir şey yapıyor. Derleyiciler benzer bir sürece sahiptir. Bu ayrım neredeyse sandığınız kadar net değildir.
Robert Harvey,

5
"JIT'in çıktısını, eski günlerde bir derleyicinin sonucu olacak olan NGen.exe'yi kullanarak gerçek bir ikili dosyada" dondurarak "aktarabilirsiniz.": bir derleyiciden (tam zamanında derleyici). Derleyicinin ne zaman çalıştırıldığı önemli değil, ne işe yaradığı. Bir derleyici girdi olarak bir kod parçasının gösterimini alır ve yeni bir gösterime gönderir. Bir tercüman bu kod parçasını çalıştırmanın sonucunu çıkaracaktır. Bunlar, nasıl karıştırdığınız ve ne zaman gerçekleştirdiğiniz önemli değil, iki farklı süreçtir.
Giorgio,

4
"Derleyici", GCC'ye eklemek için seçtikleri bir terimdir. Makine kodu üretse bile, NGen'e derleyici çağırmamayı seçti, bunun yerine bu adımı bir önceki adıma eklemeyi tercih etti (tartışmalı olarak tercüman olarak da adlandırılabilir), makine kodu üretmesine rağmen (bazı tercümanlar da bunu yapar). Demek istediğim, bugünlerde, “her zaman aradıkları şey” den başka bir şeyi kesin olarak derleyici veya tercüman olarak çağırmaya çağırabileceğiniz bağlayıcı bir ilke bulunmuyor.
Robert Harvey,

4
Çok sınırlı bir anlayışa sahip olduğum için, bugünlerde x86 işlemciler yine de donanım tabanlı JIT motorları olma yolunda yarı yoldalar.
Leushenko

4
@RobertHarvey, bir tercüman ve bir derleyicide kullanılan teknikler arasında net bir bölme çizgisi olmadığı konusunda hemfikirken, fonksiyonda oldukça net bir bölünme yoktur: eğer belirli bir aracın giriş olarak bir program koduyla çalıştırılması sonucu program, araç bir tercümandır. Sonuç, programın daha az soyut bir forma çevrilmesi sonucuysa, bir derleyicidir. Sonuç daha soyut bir forma çeviri ise, bir decompiler ise. Bununla birlikte, bu sonuçlardan birden fazlasının belirsiz olduğu durumlar.
Jules

34

Aşağıda verdiğim özet, "Derleyiciler, İlkeler, Teknikler ve Araçlar", Aho, Lam, Sethi, Ullman, (Pearson International Edition, 2007), sayfalar 1, 2'ye, bazı fikirlerimin de eklenmesine dayanmaktadır.

Bir programın işlenmesi için iki temel mekanizma derleme ve yorumlamadır .

Derleme, belirli bir dilde bir kaynak programın girişini yapar ve bir hedef dilde bir hedef program çıkarır.

source program --> | compiler | --> target program

Hedef dil makine koduysa, doğrudan bazı işlemcilerde çalıştırılabilir:

input --> | target program | --> output

Derleme, tüm giriş programının (veya modülün) taranmasını ve çevrilmesini içerir ve yürütülmesini gerektirmez.

Yorum, kaynak programın girişini ve girişini alır ve kaynak programın çıktısını üretir.

source program, input --> | interpreter | --> output

Yorum genellikle programın her seferinde bir ifadeyi işlemesini (analiz etmeyi ve yürütmeyi) içerir.

Uygulamada, birçok dil işlemcisi bu iki yaklaşımın bir karışımını kullanır. Örneğin, Java programları ilk önce bir ara programa (bayt kodu) çevrilir (derlenir):

source program --> | translator | --> intermediate program

Bu adımın çıktısı daha sonra sanal bir makine tarafından yürütülür (yorumlanır):

intermediate program + input --> | virtual machine | --> output

İşleri daha da karmaşık hale getirmek için JVM, bayt kodunu başka bir formata dönüştürmek için çalışma zamanında tam zamanında derleme yapabilir.

Ayrıca, makine dilini derlerken bile, temel işlemci tarafından uygulanan ikili dosyanızı çalıştıran bir tercüman vardır. Bu nedenle, bu durumda bile bir derleme + yorumlama melezi kullanıyorsunuz.

Bu nedenle, gerçek sistemler ikisinin bir karışımını kullanır, bu nedenle belirli bir dil işlemcisinin bir derleyici mi yoksa tercüman mı olduğunu söylemek zordur, çünkü işleminin farklı aşamalarında her iki mekanizmayı da muhtemelen kullanacaktır. Bu durumda, başka, daha tarafsız bir terim kullanmak muhtemelen daha uygun olacaktır.

Bununla birlikte, derleme ve yorumlama, yukarıdaki şemalarda açıklandığı gibi, iki ayrı işleme tipidir.

İlk soruları cevaplamak için.

Bir derleyici doğrudan fiziksel donanımda çalışan bir makine dili oluşturabilir mi?

Zorunlu olarak, bir derleyici, bir makine Mİ için yazılmış bir programı, bir makine M2 için yazılmış eşdeğer bir programa çevirir. Hedef makine donanımda uygulanabilir veya sanal bir makine olabilir. Kavramsal olarak hiçbir fark yoktur. Önemli olan, bir derleyicinin bir kod parçasına bakıp onu çalıştırmadan başka bir dile çevirmesidir.

Yani bir tercüman makine dili üretmiyor ama bir derleyici girişi için kullanıyor mu?

Eğer üreterek çıktıya atıfta bulunuyorsanız, derleyici makine dilinde olabilecek bir hedef program üretir, tercüman yapmaz.


7
Başka bir deyişle: bir tercüman P programını alır ve O çıktısını verir, bir derleyici P alır ve O çıktısını P alır; tercümanlar genellikle derleyici olan bileşenleri (örneğin bir bayt koduna, bir ara gösterime veya JIT makine talimatlarına) içerir ve benzer şekilde bir derleyici bir tercüman içerebilir (örneğin derleme zamanı hesaplamalarını değerlendirmek için).
Jon Purdy

"bir derleyici bir tercüman içerebilir (örneğin, derleme zamanı hesaplamalarını değerlendirmek için)": İyi nokta. Lisp makroları ve C ++ şablonları bu şekilde önceden işlenmiş olabilir sanırım.
Giorgio

Daha da basit, C önişlemcisi C kaynak kodunu CPP direktifleriyle düz C'ye derler ve böyle boolean ifadeleri için bir tercüman içerir defined A && !defined B.
Jon Purdy

@JonPurdy Buna katılıyorum ama aynı zamanda kaynağın belki de belirtilmiş bir versiyonunun ötesinde ara gösterimlerden faydalanmayan bir sınıf, "geleneksel tercümanlar" da eklerdim. Örnekler mermiler, birçok BASIC, klasik Lisp, 8.0'dan önce Tcl ve bc olabilir.
Ocaklar

1
@ naxa - Lawrence'ın cevabını ve Paul Draper'ın derleyici türleri hakkındaki yorumlarını görün. Bir birleştirici, (1) çıkış dilinin bir makine veya sanal makine tarafından doğrudan yürütülmesi için tasarlandığı ve (2) giriş ifadeleri ile çıkış talimatları arasında birebir yazışmaların yapıldığı özel bir derleyici türüdür.
Jules

22

Bir derleyici makine dili oluşturur

Hayır. Derleyici, girdi olarak A dilinde yazılmış bir program alan ve çıktı olarak B dilinde anlamsal olarak eşdeğer bir program üreten bir programdır . B dili herhangi bir şey olabilir, makine dili olması gerekmez.

Bir derleyici, yüksek seviyeli bir dilden başka bir yüksek seviyeli dile (örneğin, Java'yı ECMAScript'i derleyen GWT), yüksek seviyeli bir dile, düşük seviyeli bir dile (örneğin, Scheme'den C'ye derleyen Gambit) derleyebilir. yüksek seviyeli bir dilden makine koduna (örneğin, Java'yı yerel koda derleyen GCJ), düşük seviyeli bir dilden yüksek seviyeli bir dile (örn. C'yi Java, Lua, Perl, ECMAScript ve Common gibi derleyen Clue) Lisp), düşük seviyeli bir dilden başka bir düşük seviyeli dile (örneğin JVML bayt kodunu Dalvik bayt koduna derleyen Android SDK), düşük seviyeli bir dilden makine koduna (örneğin, HotSpot'un bir parçası olan C1X derleyicisine), JVML bayt kodunu makine koduna derleyen), makine kodunu yüksek seviyeli bir dile ("decompiler" denilen herhangi bir şeye), ayrıca LLVM makine kodunu ECMAScript'e derleyen Emscripten'e),makine kodunu düşük seviyeli dile (örneğin, x86 yerel kodunu JVML bayt koduna derleyen JPC'deki JIT derleyicisi) ve yerel kodu yerel koda (örneğin, PowerPC yerel kodunu x86 yerel koduna derleyen PearPC'deki JIT derleyicisi).

Ayrıca "makine kodu" nun çeşitli nedenlerden dolayı gerçekten bulanık bir terim olduğuna dikkat edin. Örneğin, yerel olarak JVM bayt kodunu çalıştıran CPU'lar var ve x86 makine kodu için yazılım yorumlayıcıları var. Öyleyse, bir "yerel makine kodu" yapan, diğeri olmayan nedir? Ayrıca, her dil, o dil için soyut bir makinenin kodudur.

Özel işlevler gerçekleştiren derleyiciler için birçok özel ad vardır. Bunların özel isimler olmasına rağmen, bunların hepsi hala derleyicilerdir, sadece özel derleyicilerdir:

  • Eğer A dili kabaca B diliyle aynı düzeyde bir soyutlama olarak algılanırsa , derleyiciye bir aktarıcı denilebilir (örn. bir Ruby to ECMAScript çevirici veya bir ECMAScript2015-ECMAScript5-transpiler)
  • Dil halinde bir dil daha soyutlama daha düşük seviyede bir düzeyde olduğu algılanmaktadır B , derleyici adlandırılabilecek Decompiler (örneğin, bir 86-makine-kod için-Cı-Decompiler)
  • eğer A dili == B dili ise, derleyiciye optimizer , obfuscator veya minifier denilebilir (derleyicinin özel işlevine bağlı olarak)

doğrudan fiziksel donanımda çalışan nedir?

Şart değil. Tercüman veya sanal makinede çalıştırılabilir. Farklı bir dile daha derlenebilir.

Yani bir tercüman makine dili üretmiyor ama bir derleyici girişi için kullanıyor mu?

Tercüman hiçbir şey üretmez. Sadece programı çalıştırıyor.

Bir derleyici bir şey üretir, ancak mutlaka makine dili olması gerekmez, herhangi bir dil olabilir. Giriş diliyle aynı dilde bile olabilir! Örneğin, Supercompilers, LLC, Java'yı girdi olarak alan ve optimize edilmiş Java'yı çıktı olarak üreten bir derleyiciye sahiptir. ECMAScript'i girdi olarak alan ve çıktıları olarak optimize edilmiş, küçültülmüş ve karıştırılmış ECMAScript'i üreten birçok ECMAScript derleyicisi vardır.


Ayrıca ilginizi çekebilir:


16

Bence "derleyiciye karşı tercüman" kavramını tamamen bırakmalısınız , çünkü bu yanlış bir ikiliktir.

  • Bir derleyici bir olan trafo : Bir yazılmış bir bilgisayar programı dönüştüren kaynak dilde ve eşdeğer bir çıkışı hedef dile . Genellikle, kaynak dil, hedef dilden daha üst düzeydedir - ve eğer tersi ise, genellikle bu tür bir transformatöre decompiler diyoruz .
  • Bir tercüman bir olan yürütme motoru . Bu dilin özelliklerine göre bir dilde yazılmış bir bilgisayar programı yürütür. Çoğunlukla yazılım terimini kullanıyoruz (ancak bir şekilde, klasik bir CPU, makine kodu için donanım tabanlı bir "tercüman" olarak görülebilir).

Soyut bir programlama dilini gerçek dünyada faydalı hale getirmek için kullanılan ortak kelime uygulamadur .

Geçmişte, bir programlama dili uygulaması çoğu zaman sadece bir derleyiciden (ve bunun için oluşturduğu CPU'dan) veya sadece bir tercümandan oluşuyordu - bu yüzden bu iki tür araç birbirini dışlayan gibi gözüküyor olabilirdi . Bugün, bunun böyle olmadığını açıkça görebiliyorsunuz (ve hiçbir zaman başlamayacaktı). Sofistike bir programlama dili uygulamasının alınması ve "derleyici" veya "tercüman" adının kullanılmaya çalışılması, genellikle sonuçsuz veya tutarsız sonuçlara yol açacaktır.

Tek bir programlama dili uygulaması , çoğu kez birden fazla biçimde (bağımsız, anında), statik analizörler ve en iyi duruma getiriciler gibi herhangi bir sayıda başka aracı ve herhangi bir sayıda adımı içeren herhangi bir sayıda derleyici ve tercüman içerebilir . Herhangi bir sayıda ara dilin (uygulanmakta olanla ilgisi olmayan) tüm uygulamalarını bile içerebilir.

Uygulama şemalarına örnekler:

  • C'yi x86 koduna dönüştüren AC derleyicisi ve bu kodu çalıştıran bir x86 işlemcisi.
  • C'yi LLVM IR'ye dönüştüren AC derleyici, LLVM IR'yi x86 makine koduna dönüştüren bir LLVM arka uç derleyicisi ve bu kodu çalıştıran bir x86 CPU.
  • C'yi LLVM IR'ye dönüştüren AC derleyici ve LLVM IR'yi yürüten bir LLVM yorumlayıcısı.
  • Java'yı JVM bayt koduna dönüştüren bir Java derleyicisi ve bu kodu yürüten bir tercümana sahip bir JRE.
  • Java'yı JVM bayt koduna dönüştüren bir Java derleyicisi ve bu kodun bazı bölümlerini yürüten bir tercüman ve bu kodun diğer bölümlerini x86 makine koduna dönüştüren bir derleyici ve bu kodu yürüten bir x86 CPU'su olan bir JRE.
  • Java'yı JVM bayt koduna dönüştüren bir Java derleyicisi ve bu kodu çalıştıran bir ARM CPU.
  • C # 'yi CIL'ye dönüştüren AC # derleyicisi, CIL'i x86 makine koduna dönüştüren bir derleyiciye sahip bir CLR ve bu kodu çalıştıran bir x86 işlemcisi.
  • Ruby'yi çalıştıran bir Ruby tercümanı.
  • Hem Ruby'yi çalıştıran bir yorumlayıcı hem de Ruby'yi x86 makine koduna dönüştüren bir derleyici ve bu kodu çalıştıran bir x86 işlemci içeren bir Ruby ortamı.

...ve bunun gibi.


Ara gösterim için tasarlanan kodlamaların bile (örn. Java bytecode) donanım uygulamalarına sahip olabileceğine dikkat çekmek için +1.
Jules

7

Derleyiciler ve tercümanlar arasındaki çizgiler zaman içinde bulanıklaştığı halde, programın ne yapması gerektiği ve derleyici / tercümanın ne yaptığı anlamına bakılarak aralarında bir çizgi çekilebilir.

Bir derleyici başka bir program (genellikle makine kodu gibi daha düşük bir dilde) üretecektir, eğer bu program çalışıyorsa programınızın yapması gerekeni yapar.

Bir tercüman programınızın yapması gerekeni yapar.

Bu tanımlarla bulanıklaştığı yerler, derleyicinizin / tercümanınızın, nasıl baktığınıza bağlı olarak farklı şeyler yaptığını düşündüğü durumlardır. Örneğin, Python, Python kodunuzu alır ve derlenmiş bir Python bayt kodunda derler . Bu Python bayt kodu bir Python bayt kodu yorumlayıcısı aracılığıyla çalıştırılıyorsa , programınızın yapması gerekeni yapar. Çoğu durumda, bununla birlikte, Python geliştiricileri düşünmek tercih böylece, tek bir büyük adımda yapılıyor adımların her ikisini de düşünmek CPython olarak tercüman yorumlayarak kendi sourcecode ve var olduğu gerçeği derlenmiş yol boyunca bir uygulama ayrıntı olarak kabul edilir . Bu şekilde, hepsi bir bakış açısı meselesi.


5

İşte derleyiciler ve tercümanlar arasındaki basit bir kavramsal açıklamasını İşte.

3 dili düşünün: programlama dili, P (programın yazıldığı yer); etki alanı dili, D (çalışan programla devam eden şeyler için); ve hedef dil, T (bazı üçüncü diller).

kavramsal olarak,

  • bir derleyici P'yi T'ye çevirir, böylece T (D) 'yi değerlendirebilirsiniz; buna karşılık

  • Bir tercüman P (D) yi doğrudan değerlendirir.


1
Modern tercümanların çoğu kaynak dili doğrudan değerlendirmez, kaynak dilin orta dereceli temsilini görür.
Robert Harvey,

4
@RobertHarvey Bu, terimler arasındaki kavramsal farkı değiştirmez.
Lawrence

1
Yani tercüman olarak gerçekten bahsettiğiniz şey, ara gösterimi değerlendiren kısımdır. Ara gösterimi yaratan kısım, tanımınız gereği bir derleyicidir .
Robert Harvey,

6
@RobertHarvey Gerçekten değil. Terimler, üzerinde çalıştığınız soyutlama seviyesine bağlıdır. Altına bakarsanız, araç her şeyi yapıyor olabilir. Benzetme yaparak, yabancı bir ülkeye gidip iki dilli bir arkadaşınızı Bob'a getirdiğinizi söyleyin. Yerlilerle sırayla konuşan Bob ile konuşarak yerellerle iletişim kurarsanız, Bob size (tercüman olmadan önce kendi dillerinde karalamalar yapsa bile) tercüman olarak hareket eder. Bob'dan cümleleri istiyorsan ve Bob yabancı dilde yazarsa, ve bu yazılara atıfta bulunarak yerel halkla iletişim kurarsan (Bob değil) Bob senin için bir derleyici görevi görür.
Lawrence

1
Mükemmel cevap Kayda değer: Bugünlerde "transpiler" ifadesini duyabilirsiniz. Bu, P ve T'nin benzer soyutlama seviyeleri olduğu bir derleyicidir. (Örn: ES5 - ES6 aktarıcısı.)
Paul Draper
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.