SEN2001 · 1. hafta · Introduction

Uygulama yöntemleri ve dillerin evrimi

Compilation, pure interpretation ve hybrid uygulama; derleyicinin fazları, linker ve preprocessor, JIT; programlama ortamları ve Fortran'dan Java'ya dillerin evriminde sınavda sorulan kilometre taşları.

compilercompilationlexical analyzersyntax analyzersemantic analyzerintermediate codecode generatorsymbol tablelinkerload modulepure interpretationhybrid implementationbytecodevirtual machinejust-in-time compilerpreprocessormacroprogramming environmentFortranLISPALGOL 60COBOLSIMULA 67SmalltalkPrologAdaC++Java

Bir dili yazmak bir şey, onu bir bilgisayarda çalıştırmak başka bir şey. Bu sayfa iki konuyu kapsar: dillerin nasıl uygulandığı (compilation, interpretation, hybrid) ve dillerin evriminden sınavda sorulan kilometre taşları. Vizede kısa cevaplı ve eşleştirme soruları olarak çıkar; az emekle alınan puanlar.

Altın kurallar:

  1. Compilation: yavaş çeviri, hızlı çalışma. Interpretation: çeviri yok, yavaş çalışma.
  2. Hybrid = ara dile derle + yorumla. JIT bunu hızlandırır.
  3. Preprocessor metinsel değiştirme yapar, hesaplamaz.
  4. Tarihte “ilk”leri bil: Fortran ilk derlenen dil, ALGOL 60 ilk BNF, SIMULA 67 ilk sınıf, LISP ilk fonksiyonel.

Uygulama yöntemleri

Bilgisayarın donanımı sadece makine dilini çalıştırır. Yüksek seviyeli bir dil üç yolla çalıştırılabilir.

Compilation

Kaynak program bir kez makine diline çevrilir, sonra doğrudan çalışır. Çeviri yavaş, çalışma hızlı. C, C++, COBOL, Ada.

kaynak program
   │  lexical analyzer      karakterler → lexical units (lexeme)
   ▼
lexical units
   │  syntax analyzer       → parse trees
   ▼
parse trees
   │  intermediate code generator ve semantic analyzer
   ▼
ara kod   ──(optimizasyon, isteğe bağlı)
   │  code generator
   ▼
makine dili ── linker (+ kütüphane ve sistem kodu) ──► load module ──► çalışır

symbol table: tüm fazlara kullanıcı tanımlı isimlerin tip ve niteliklerini sağlar
  • Lexical analyzer: karakterleri identifier, özel kelime, operatör, noktalama gibi birimlere toplar; yorumları atlar.
  • Syntax analyzer: bu birimlerden parse tree kurar.
  • Semantic analyzer: tip hataları gibi sözdiziminin yakalayamadığı hataları kontrol eder; ara kod üretir.
  • Optimization: programı küçültür ya da hızlandırır (genelde ara kod üzerinde).
  • Code generator: makine kodunu üretir.
  • Linker: kullanıcı programını sistem ve kütüphane programlarıyla bağlar; çıktı load module (executable image).

Bir program çalışırken komutlar bellekten işlemciye taşınır; bu bağlantı genelde işlemciden yavaştır ve hızı sınırlar (von Neumann bottleneck).

Pure interpretation

Çeviri yok. Bir yorumlayıcı (interpreter) program, kaynak programı ifade ifade okuyup çalıştırır; yazılımla taklit edilmiş bir sanal makine gibi.

  • Artı: hata mesajı doğrudan kaynak satırına ve değişkene işaret eder; debug kolay.
  • Eksi: 10 ila 100 kat yavaş. Darboğaz, her ifadenin her çalıştırılışta yeniden decode edilmesi. Ayrıca kaynak program ve symbol table çalışırken bellekte durur.
  • Örnekler: erken JavaScript ve PHP, LISP’in ilk sürümleri, APL. Web betik dilleriyle geri döndü.

Hybrid implementation

Kaynak program, yorumlanması kolay bir ara dile derlenir; ara dil yorumlanır. Saf yorumlamadan hızlı, çünkü kaynak ifadeler sadece bir kez decode edilir.

  • Perl: önce hataları yakalamak için kısmen derlenir.
  • Java: kaynak → bytecode → JVM (Java Virtual Machine) yorumlar. Bytecode taşınabilir: JVM’i olan her makinede çalışır.

Just-in-time

JIT derleyici, bir alt program ilk çağrıldığında onun ara kodunu makine koduna çevirir ve saklar; sonraki çağrılar makine kodunu kullanır. Java ve .NET dilleri (C#) böyle çalışır. Sonuç: taşınabilir ara kod + derlenmiş kodun hızı.

YöntemÇeviriÇalışma hızıÖrnek
CompilationBir kez, yavaşEn hızlıC, C++, COBOL
Pure interpretationYok10-100x yavaşErken JavaScript, PHP
HybridAra dileAradaPerl, erken Java
JITAra dil + çalışırken makine kodunaDerlenmişe yakınJava, C#

Preprocessor

Programı derlemeden hemen önce işleyen bir programdır. Başka dosyaları ekler (#include), makroları açar (#define). Değiştirme metinseldir; ifade hesaplanmaz ve öncelik kuralları açılımdan sonra uygulanır.

#define SQ(x) x*x
#define SQP(x) ((x)*(x))
#define DOUBLE(x) x+x

SQ(2+3)        /* 2+3*2+3       */
SQP(2+3)       /* ((2+3)*(2+3)) */
10 * DOUBLE(3) /* 10 * 3+3      */
11
25
33

TUZAK · makro fonksiyon değildir. SQ(2+3) 25 değil 11 verir, çünkü argüman hesaplanmadan metin olarak yapıştırılır. Parametreleri ve tüm gövdeyi parantez içine al.

Programlama ortamları

Yazılım geliştirmede kullanılan araçlar topluluğu: dosya sistemi, editör, linker, derleyici, debugger. UNIX eski bir ortam; Eclipse, NetBeans, Microsoft Visual Studio .NET entegre (IDE) örnekleri.

Dillerin evrimi: sınavda sorulanlar

YılDilNeden önemli?
1945Plankalkül (Zuse)İlk yüksek seviyeli dil tasarımı; uygulanmadı
1957Fortran I (Backus, IBM)İlk yaygın derlenen yüksek seviyeli dil; derlenmiş kodun verimli olabileceğini gösterdi
1958LISP (McCarthy)İlk fonksiyonel dil; liste işleme, garbage collection; yapay zekâ
1958-60ALGOL 58 / ALGOL 60Makineden bağımsız; BNF ile tanımlanan ilk dil; blok yapısı, özyineleme, pass-by-value ve pass-by-name
1960COBOLİş uygulamaları; kayıtlar (record), ondalık aritmetik, okunur İngilizce benzeri sözdizimi
1964BASICZaman paylaşımlı, öğrenmesi kolay
1964PL/IBilimsel + iş; ilk istisna yönetimi ve eşzamanlılık denemeleri; çok karmaşık
1967SIMULA 67Sınıflar ve nesneler; veri soyutlamanın temeli
1971Pascal (Wirth)Öğretim için; yapısal programlama
1972CSistem programlama (UNIX); güçlü operatörler, zayıf tip kontrolü
1972PrologMantık programlama
1980Smalltalk-80İlk tam OOP: her şey nesne, mesaj gönderme; grafik arayüz
1983AdaABD Savunma Bakanlığı; paketler, istisna yönetimi, generic’ler, task’lar
1985C++C + sınıflar, çoklu kalıtım, operator overloading, template
1995JavaC++ temelli, daha basit ve güvenli: pointer yok, garbage collection, applet’ler, bytecode
2000C#.NET; Java ve C++ fikirleri, delegate, property

Betik diller: Perl (1987, metin işleme), JavaScript (1995, tarayıcı), PHP (1995, sunucu), Python (1991), Ruby (1996, her şey nesne). Fonksiyonel: Scheme (1975, LISP’in küçük lehçesi), ML (statik tip, type inference), Haskell (saf ve lazy).

İPUCU · “ilk” soruları. İlk derlenen: Fortran. İlk BNF: ALGOL 60. İlk sınıf: SIMULA 67. İlk tam OOP: Smalltalk. İlk fonksiyonel ve garbage collection: LISP. Mantık: Prolog. İş: COBOL. Bu yedi eşleşme bu bölümün puanlarının çoğunu getirir.

Sık yapılan hatalar

YanlışDoğrusu
Yorumlama yavaş çünkü makine komutu yavaşHer ifade her seferinde decode edilir
Java saf yorumlanırBytecode + JVM (hybrid), bugün JIT
JIT tüm programı başta derlerAlt programı ilk çağrıda derler ve saklar
Optimizasyon zorunlu fazİsteğe bağlı
Linker kaynak kodu derlerDerlenmiş parçaları kütüphanelerle bağlar
SQ(2+3) = 25x*x makrosuyla 11
İlk BNF Fortran’daALGOL 60 (ALGOL 58 için kullanıldı)
İlk OOP dili SmalltalkSınıflar SIMULA 67’de; ilk tam OOP Smalltalk

Kendini test et

Sınavdaki gibi İngilizce sorular. Önce kâğıt kalemle çöz, sonra cevabı aç.

Soru 1kolay

Put the phases of a compiler in order: code generation, syntax analysis, lexical analysis, semantic analysis / intermediate code generation, optimization (optional).

Cevabı göster
lexical analysis, syntax analysis, semantic analysis / intermediate code, optimization, code generation

Lexer karakterleri lexeme'lere toplar. Parser bunlardan parse tree kurar. Semantic analyzer tip hatalarını kontrol eder ve ara kod (intermediate code) üretir. İsteğe bağlı optimizasyon programı küçültür ya da hızlandırır. Code generator makine kodunu üretir. Symbol table tüm fazlara hizmet eder.

Soru 2kolay

Which compiler phase turns the characters of the source program into lexical units, and which builds parse trees?

Cevabı göster
lexical analyzer; syntax analyzer

Lexical units: identifier, özel kelime, operatör, noktalama. Lexer yorumları ve boşlukları atlar. Syntax analyzer (parser) lexical unit'lerden programın sözdizimsel yapısını gösteren parse tree'leri kurar.

Soru 3orta

Why is pure interpretation typically 10 to 100 times slower than running compiled code?

Cevabı göster
every statement must be decoded each time it is executed

Yorumlayıcı kaynak ifadeyi her çalıştırışta yeniden çözümlemek zorunda; bir döngüde aynı satır binlerce kez çözümlenir. Darboğaz ifadenin decode edilmesidir, makine komutlarının kendisi değil. Ayrıca kaynak program ve symbol table çalışırken bellekte durur. Artısı: hata mesajları kaynak satırına işaret eder, debug kolaydır.

Soru 4kolay

Classify the implementation method: (a) C and COBOL; (b) early JavaScript and PHP; (c) Perl and early Java.

Cevabı göster
(a) compilation (b) pure interpretation (c) hybrid

Compilation: kaynak bir kez makine diline çevrilir, çalışma hızlı. Pure interpretation: çeviri yok, yorumlayıcı kaynağı doğrudan çalıştırır. Hybrid: kaynak, yorumlanması kolay bir ara dile (Java bytecode) çevrilir, sonra bu ara dil yorumlanır (JVM).

Soru 5orta

What does a just-in-time (JIT) compiler do?

Cevabı göster
it translates intermediate code (e.g. bytecode) into machine code the first time a method is called, and keeps it for later calls

JIT, hybrid sistemin yavaşlığını giderir: program ara dile derlenir; bir alt program ilk kez çağrıldığında onun ara kodu makine koduna çevrilir ve saklanır, sonraki çağrılar doğrudan makine kodunu çalıştırır. Java ve .NET dilleri bu yolla çalışır. Yani JIT aslında gecikmeli bir derleyicidir.

Soru 6orta

With the C macro #define SQ(x) x*x, what is the value of SQ(2+3)? How should the macro be written?

Cevabı göster
11; #define SQ(x) ((x)*(x)) gives 25

Preprocessor derlemeden önce metinsel değiştirme yapar, ifadeyi hesaplamaz. SQ(2+3) → 2+3*2+3; çarpma önce: 2 + 6 + 3 = 11. Parantezli tanımla ((2+3)*(2+3)) = 25 olur.

Soru 7zor

With #define DOUBLE(x) x+x, what is the value of 10 * DOUBLE(3)?

Cevabı göster
33

Açılım: 10 * 3+3. Önce çarpma: 30 + 3 = 33 (beklenen 60 değil). Makronun tüm gövdesi de parantez içinde olmalı: #define DOUBLE(x) ((x)+(x)).

Soru 8kolay

What does a linker do?

Cevabı göster
it combines the user's compiled program with system and library programs to produce a load module (executable image)

Kullanıcı programı genelde başka programlara (işletim sistemi rutinleri, kütüphane fonksiyonları) ihtiyaç duyar. Linker bunları bağlayıp tek bir çalıştırılabilir dosya (load module) üretir. Kütüphane çağrısının fonksiyonun koduna bağlanması bu yüzden link time'da olur.

Soru 9kolay

Name the language: (a) the first widely used compiled high-level language (1957); (b) the first language described with BNF; (c) the language that introduced classes (1967); (d) designed for business data processing.

Cevabı göster
(a) Fortran I (b) ALGOL 60 (c) SIMULA 67 (d) COBOL

Fortran (John Backus, IBM 704) derlenmiş kodun hızlı olabileceğini kanıtladı. ALGOL 60 BNF ile tanımlandı ve blok yapısı, özyineleme, pass-by-value/name getirdi. SIMULA 67 simülasyon için sınıfları ve nesneleri getirdi. COBOL (1960) iş uygulamaları için kayıtlar ve ondalık sayılar.

Soru 10kolay

Which language introduced list processing and garbage collection, and which was the first purely object-oriented language?

Cevabı göster
LISP; Smalltalk

LISP (1958, John McCarthy) yapay zekâ için tasarlandı: tek veri yapısı liste, hesaplama fonksiyon uygulaması, kullanılmayan bellek otomatik toplanır. Smalltalk (Xerox PARC, Smalltalk-80) her şeyin nesne olduğu ve hesaplamanın mesaj göndermeyle yapıldığı ilk tam OOP dili; grafik pencere arayüzünü de tanıttı.

Soru 11orta

Order these chronologically: Java, Prolog, Fortran I, SIMULA 67, Smalltalk-80.

Cevabı göster
Fortran I, SIMULA 67, Prolog, Smalltalk-80, Java

Fortran I 1957, SIMULA 67 1967, Prolog 1972, Smalltalk-80 1980, Java 1995. Sınavda yıl ezberi değil sıra ve "hangi fikir ilk nerede?" sorulur.

Soru 12kolay

Which language was designed for the U.S. Department of Defense and is known for packages, exception handling, generic units and tasks (concurrency)?

Cevabı göster
Ada

Ada (1983) çok büyük bir tasarım sürecinin ürünü: paketlerle veri soyutlama, ayrıntılı istisna yönetimi, generic program birimleri, task'larla eşzamanlılık. Ada 95 OOP desteği ekledi. Karmaşıklığı ve derleyici maliyeti yayılmasını sınırladı.

Doğrulama: Preprocessor makro soruları, makro gövdesi metinsel olarak açılıp ortaya çıkan ifade node ile hesaplanarak doğrulandı (verify/SEN2001/01.mjs); C derleyicisi kurulu olmadığı için gerçek cpp çalıştırılmadı. Faz sıraları ve yıllar kavramsal/tarihsel bilgi; ders kitabının standart anlatımıyla karşılaştırıldı.

Deftere not kartı

derleyici fazları: lexical → syntax → semantic/ara kod → (optimizasyon) → code generation symbol table hepsine hizmet eder. linker: kütüphanelerle → load module compilation: yavaş çeviri, HIZLI çalışma (C, C++, COBOL) pure interpretation: çeviri yok, 10-100x yavaş (decode), kolay debug (erken JS, PHP) hybrid: ara dil + yorumlayıcı (Perl, Java bytecode + JVM) JIT: ara kodu ilk çağrıda makine koduna çevir, sakla (Java, .NET) preprocessor: derlemeden ÖNCE metinsel değiştirme. #define SQ(x) x*x → SQ(2+3) = 11 doğru makro: ((x)*(x)) ve dış parantez Fortran I 1957 ilk derlenen yüksek seviyeli dil LISP 1958 fonksiyonel, liste, garbage collection ALGOL 60: BNF ile tanımlanan ilk dil, blok yapısı, özyineleme COBOL 1960 iş; SIMULA 67 sınıflar; Prolog 1972 mantık Smalltalk-80 ilk tam OOP; C 1972 sistem; C++ 1985; Ada 1983; Java 1995