Devo utilizzare un compilatore sorgente-sorgente o tradizionale per sviluppare il mio linguaggio di programmazione?

4

Sono davvero interessato a scrivere il mio linguaggio di programmazione generale ad alto livello, ma sono un po 'confuso.

So che Python e Ruby sono stati scritti in C, il che mi fa pensare che se voglio scrivere il mio 'Python', è preferibile usare un compilatore source-to-source per tradurre tutto il codice sorgente della mia lingua in C, o dovrei scegliere come linguaggio assembly?

Il punto è, so che ho bisogno di scavare in Compiler Design e comprendere l'analisi lessicale e l'intero processo di analisi del codice e generazione di token e un linguaggio intermedio e controllo di errori sintattici e semantici e quindi generazione del codice di output.

Tuttavia, dal momento che non sono un esperto in programmazione di basso livello / assembly, dovrei usare un compilatore source-to-source? Quali sfide potrei affrontare se tento di compilare la mia lingua all'assemblaggio? Quali svantaggi potrebbero esserci nell'usare un compilatore source-to-source? Quali aspetti specifici della mia situazione dovrei prendere in considerazione quando prendo questa decisione?

    
posta Ericson Willians 27.05.2015 - 01:13
fonte

6 risposte

12

Mi concentrerò sulla tua domanda principale, poiché ad altre cose è stata data una risposta altrove.

Should you target a higher level language or assembly?

Ottenere software è difficile. Mentre si crea un nuovo linguaggio può essere abbastanza semplice, è necessario attenersi a cose semplici ed evitare ciò che è un dolore da implementare. Fare la tua prima lingua ha il problema di non sapere quale sia il "dolore da implementare". E diciamocelo, non stai mirando a creare un nuovo linguaggio che possa implementare solo calcolatori basati su console - le cose interessanti saranno non banali da implementare.

Quindi fai un favore a te stesso e scegli come target una lingua che già conosci. Creare un nuovo linguaggio e un compilatore funzionale è abbastanza difficile senza aggiungere "learn assembly" all'elenco delle attività. Preparandoti al successo, è più facile divertirti e imparare dallo sforzo.

    
risposta data 27.05.2015 - 05:08
fonte
5

Dovresti considerare di compilarlo in C (vedi questo e that risposte), o in altri linguaggi (Java, Common Lisp, Ocaml, o anche un mix di Javascript & C - come HOP fa ...) Puoi anche compilare la rappresentazione testuale di LLVM bytecode oppure utilizzare la libreria LLVM come back-end o (se si utilizza GCC 5 o versione successiva) utilizzare libgccjit (per scegliere come target Rappresentazioni interne GCC e profitti dalle ottimizzazioni GCC). Puoi anche scegliere alcuni bytecode esistenti (ad es. JVM, Ocaml, Neko, Parrot, ...) e compilarli. E potresti anche usare qualche libreria JIT come libjit , GNU lightning, asmjit etc ...

Lexing & l'analisi è non il lavoro principale di un compilatore o di un interprete. Sono le parti semplici. Un compilatore è principalmente che trasforma (molto spesso in più passaggi) alcune rappresentazioni interne (in particolare Abstract Syntax Trees , ma non solo loro) del codice sorgente che sta compilando. Un interprete spesso trasforma alcune rappresentazioni interne, quindi attraversa altre (ad esempio qualche bytecode o qualche AST normalizzato). Gioca con l'opzione GCC -fdump-tree-all , e forse con MELT (un DSL simile a Lisp per ispezionare e / o trasformare le rappresentazioni interne GCC). La semantica del tuo linguaggio di programmazione è più importante della sintassi.

Una parte importante è gestione della memoria . Vuoi un garbage collector (è una parte fondamentale della tua semantica)? Che dire di digitando (statico o dinamico) & tipo di inferenza ? Gestisci chiamate di coda ? Vuoi omoiconicity ? metaprogramming ? Vuoi chiusure (hanno più spesso bisogno di un GC)? Considera GC conservativo di Boehm e / o leggi il manuale GC .

Bootstrapping i compilatori sono importanti. Vedi anche questo e i riferimenti che ho fornito lì. Leggi anche questo & che risponde spiegando tecniche e amp; dettagli pratici (e dovrebbe curare il tuo mal di testa su "Haskell scritto in Haskell", "Ocaml scritto in Ocaml", "MELT scritto in MELT", "CAIA scritto in CAIA", "GCC o Clang / LLVM scritto in C ++").

Inoltre, se non ne conosci nessuno, gioca con Ocaml, Common Lisp, o Haskell o Scheme (vedi anche SICP ). Leggi il libro di Scott su Programming Language Pragmatics e il libro di Queinnec su Lisp In Small Pieces .

Assicurati di implementare la tua lingua un software gratuito (su link troverai molte altre implementazioni linguistiche, ad es. compilatori o interpreti.

    
risposta data 27.05.2015 - 07:01
fonte
2

Ho fatto un po 'di lavoro professionale tre anni fa che utilizzava la reflection per capire un'interfaccia .NET e fornire una colla CIL per manipolarla su una classe base. Ha aperto gli occhi al livello di lavoro aggiuntivo richiesto.

La maggior parte dello sviluppo del software, ti concentri sulle rotte di successo e se succede qualcosa di inaspettato, prendi un'eccezione. Ho scoperto che il percorso di successo era inferiore al 20% del lavoro. La normale strategia di intercettazione delle eccezioni non funziona, poiché le eccezioni si verificano in fase di esecuzione, non quando si genera il codice. Invece devi pensare e verificare eventuali combinazioni che potrebbero infrangere il tuo codice e quindi supportarlo o fallire la compilazione. Questo è molto diverso dallo sviluppo dell'applicazione.

Se vuoi creare un nuovo linguaggio di programmazione e vuoi che venga adottato da altri, la soluzione migliore è trovare un problema che al momento non può essere facilmente risolto. Se crei un nuovo linguaggio di programmazione che fornisca un approccio semplice e pulito per risolvere un problema complesso, le persone con questo problema hanno una buona ragione per adottare la tua lingua.

    
risposta data 27.05.2015 - 09:10
fonte
1

Se traduci tutto ciò che hai in C, allora hai un sistema funzionante ovunque sia disponibile un compilatore C. Che è praticamente ovunque. Non devi preoccuparti di diversi processori, diversi sistemi operativi e tutto il resto.

Potresti invece compilare in C ++, che oggi è quasi comune come C, e ti dà il vantaggio che puoi nascondere il lavoro che devi fare in una classe invece di doverti ripetere . Importante se il tuo linguaggio ha oggetti che non possono essere tradotti in primitive C o C ++.

    
risposta data 27.05.2015 - 12:42
fonte
1

"Sono davvero interessato a scrivere il mio linguaggio di programmazione generale ad alto livello" Sei veramente? Se sei veramente interessato e vuoi creare la tua lingua completa con un compilatore (nativo) per l'esperienza che probabilmente ti interesserebbe leggere sull'assemblaggio e su come funziona la CPU, puoi esaminare l'output di assemblaggio di linguaggi di alto livello esistenti in darti un'idea.

Una fonte per il compilatore di codice macchina nativo ti dà molta più libertà di definire la semantica della tua lingua, se compili a C sei sostanzialmente limitato al modo C di fare cose, quindi nelle funzionalità finali potresti voler includere poiché le opportune chiamate di coda saranno fuori dalla tua portata. È anche probabile che la compilazione di un compilatore nativo sia un'esperienza più gratificante e illuminante, mentre la compilazione in C è fondamentalmente l'uso di qualcosa che qualcuno ha costruito C è un linguaggio molto complicato per qualcosa da esportare (la sintassi è progettata per essere buona per gli umani scrivere non è facile da generare per le macchine), è necessario preoccuparsi dell'ordine di annidamento delle dichiarazioni, assicurandosi di specificare informazioni sufficienti per consentire al compilatore C di ottimizzare il codice in modo efficace (ad esempio usando restrizioni quando non vi sono alias dei puntatori).

Se sei pragmatico e vuoi costruire un linguaggio che verrà utilizzato nel prossimo futuro e non sei realmente interessato a costruire il compilatore con tanto di compilatore funzionante per la tua lingua, il sorgente al sorgente è il strada da percorrere, tuttavia, sii consapevole che il tuo linguaggio diventa effettivamente un preprocessore (in effetti un preprocessore è un buon punto di partenza per apprendere l'analisi lessicale e l'analisi). In entrambi i casi, se il tuo obiettivo è quello di distribuire la tua lingua, cerca di evitare che diventi un linguaggio JAP (solo un altro linguaggio di programmazione) che è un linguaggio che non offre nulla di nuovo e non rappresenta un miglioramento sostanziale rispetto alle lingue esistenti.

    
risposta data 02.07.2015 - 23:57
fonte
-2

Se scegli come target LLVM, devi comunque eseguire il preprocesso e compilare effettivamente l'input, ma l'output può quindi essere in qualsiasi output che LLVM consente, sia esso assembly o JavaScript.

    
risposta data 27.05.2015 - 12:48
fonte

Leggi altre domande sui tag