È possibile (se noioso) scrivere codice macchina diretto. Magari scrivi il programma in assembler su un pezzo di carta e poi lo traduci a mano nelle istruzioni numeriche del codice macchina che inserisci nella memoria della macchina. Puoi persino saltare il passaggio assemblatore su carta se hai memorizzato i valori numerici di tutte le istruzioni del codice macchina - non insolito in quei giorni, che ci crediate o no!
I primi computer sono stati programmati direttamente in binario attivando i commutatori fisici. È stato un notevole miglioramento della produttività quando l'hardware si è evoluto per consentire al programmatore (o all'addetto all'immissione dati) di immettere il codice in numeri esadecimali tramite una tastiera!
Un assemblatore di software è diventato rilevante solo quando è disponibile più memoria (dal momento che il codice assembler occupa più spazio del codice macchina grezzo) e l'hardware si è evoluto per consentire l'input alfanumerico. Quindi i primi assemblatori sono stati scritti direttamente da persone che parlano correntemente il codice della macchina.
Quando hai un assemblatore, puoi scrivere un compilatore per un linguaggio di livello superiore nell'assemblatore.
La trama di C ha più passaggi. Il primo compilatore C è stato scritto in B (un predecessore di C) che a sua volta è stato scritto in BCPL. BCPL è un linguaggio piuttosto semplice (per esempio non ha affatto tipi), ma è comunque un passo avanti rispetto all'assemblatore non elaborato. Così vedi come gradualmente le lingue più complesse si costruiscono in linguaggi più semplici fino al montaggio. E di per sé C è un linguaggio piuttosto piccolo e semplice secondo gli standard di oggi.
Oggi, il primo compilatore per una nuova lingua è spesso scritto in C, ma quando la lingua raggiunge una certa maturità viene spesso riscritta "in sé". Il primo compilatore Java è stato scritto in C, ma successivamente è stato riscritto in Java. Il primo compilatore C # è stato scritto in C ++, ma recentemente è stato riscritto in C #. Il compilatore / interprete Python è scritto in C, ma il progetto PyPy è un tentativo di riscriverlo in Python.
Tuttavia non è sempre possibile scrivere un compilatore / interprete per una lingua nella stessa lingua. Esiste un interprete JavaScript scritto in JavaScript, ma i compilatori / interpreti nei browser correnti sono ancora scritti in C o C ++ per motivi di prestazioni. JavaScript scritto in JavaScript è semplicemente troppo lento.
Ma non devi usare C come "lingua di partenza" per un compilatore. Il primo compilatore F # è stato scritto in OCaml, che è l'altra lingua più strettamente correlata a F #. Quando il compilatore è stato completato, è stato riscritto in F #. Il primo compilatore per Perl 6 è stato scritto in Haskell (un linguaggio puramente funzionale molto diverso da Perl) ma ora ha un compilatore scritto in C.
Un caso interessante è Rust, in cui il primo compilatore è stato scritto in OCaml (ora è riscritto in Rust). Ciò è notevole perché OCaml è generalmente considerato di livello superiore rispetto a Rust, che è un linguaggio di sistema più vicino al metallo. Quindi non sono sempre le lingue di livello superiore implementate nei linguaggi di livello inferiore, potrebbe anche essere il contrario.