Sviluppo di un linguaggio dinamico

11

Ho creato diversi compilatori scritti a mano per linguaggi molto semplici, ma ora voglio cimentarmi nello sviluppo di un linguaggio dinamico, simile a un Python o Ruby semplificato. Tuttavia, per me è stato facile capire come funzionano i compilatori. I compilatori primitivi si limitano a tradurre. Ma non posso farlo se la lingua è dinamica. Devo scrivere un interprete o una macchina virtuale che tenga traccia delle informazioni in fase di esecuzione e mi faccia lavorare molto di più.

In breve, ci sono risorse che dovrei controllare considerando che so come funzionano i compilatori ma voglio migrare alla creazione di un interprete? Ci sono alcune macchine virtuali là fuori per i linguaggi dinamici, ma non ho alcun problema con il rolling mio. Questo è tutto solo per la mia esperienza personale.

Sto cercando informazioni su come passare da un compilatore a un interprete. Se ho già creato un compilatore per il linguaggio X, ma ora cosa scrivere un interprete, cosa deve essere fatto e ci sono risorse che superano il processo?

Non voglio risorse ampie o astratte su come funzionano i compilatori o le macchine virtuali. Ho molti libri di testo sull'argomento. Tutte le risorse che ho trovato online presumono che tu abbia 0 esperienze e quindi inizi con analisi lessicali o sintattiche o sono estremamente astratte. Ho un compilatore funzionante, ma ora voglio trasformarlo in un interprete e aggiungere funzioni dinamiche al linguaggio.

Non sono riuscito a trovare risorse su questo processo, potrebbe essere un ambito troppo limitato o risorse sul "back-end" di un interprete senza essere troppo teorico, motivo per cui ho postato qui.

    
posta Austin Henley 28.02.2012 - 02:03
fonte

4 risposte

4

Prima apprendi come implementare gli interpreti. Raccomando PLAI (Linguaggi di programmazione: applicazione e interpretazione) . Raggiunge rapidamente la carne dell'interpretazione senza soffermarsi troppo sulla sintassi.

Per la tua lingua, sarai in grado di riutilizzare la libreria front-end (parser, per lo più) del compilatore e la libreria run-time (GC, strutture dati, operazioni primitive, ecc.).

Naturalmente, puoi anche implementare un linguaggio dinamico con un compilatore che produce codice che manipola (alcune) le stesse strutture dati che useresti in un interprete. Ad esempio, in un interprete è possibile implementare variabili globali come tabella hash con indici stringa. In un compilatore, si compileranno i riferimenti alle variabili globali nel codice che esegue la ricerca utilizzando la stessa tabella. Al contrario, è possibile compilare le variabili lessicali in una rappresentazione più efficiente (argomenti "nativi" e riferimenti alla struttura di chiusura).

    
risposta data 28.02.2012 - 04:31
fonte
5

Se vuoi imparare le basi per implementare un interprete per un linguaggio dinamico, non riesco a immaginare un punto di partenza migliore delle origini del primissimo linguaggio di programmazione dinamico e interpretato: Lisp.

Nel suo originale giornale del 1960 , John McCarthy ha definito 5 funzioni primitive necessarie per un Lisp. Naturalmente, McCarthy intendeva solo il suo articolo su Lisp come esercizio accademico; era uno studente laureato che ha impiantato eval in assemblaggio e ha creato il primo interprete Lisp. Paul Graham identifica sette primitivi : preventivo, atom, eq, contro, auto, cdr e cond.

Il fatto è che puoi davvero implementare il Lisp in qualsiasi lingua; una volta implementato eval , è facile impostare un REPL e hai un interprete interattivo . Le persone sono state annoiate o abbastanza curiose da implementare Lisps in C, Java, Ruby, Python e in molti altri linguaggi. E non sempre di proposito; è importante ricordare Decima regola di Greenspun :

Any sufficiently complicated C or Fortran program contains an ad hoc, informally-specified, bug-ridden, slow implementation of half of Common Lisp.

Non sto dicendo che il tuo obiettivo finale dovrebbe essere un'implementazione Lisp; ma l'omoiconicità ha i suoi benefici quando impara ad implementare un linguaggio dinamico; perché affrontare i problemi di sintassi quando si può imparare su una lingua in cui la sintassi idiomatica è identica come l'AST di un linguaggio che usa un lexer / parser?

Comunque ... solo un suggerimento. Ma è una buona ragione che la maggior parte dei grandi linguaggi di programmazione da C abbia almeno un po 'della natura Lisp.

    
risposta data 28.02.2012 - 04:55
fonte
0

Ho messo questo (~ 600 righe di C #) nel dominio pubblico, che supporta quote / lista / applica / eval / test / etc, e consente di personalizzare facilmente una sintassi simile a Lisp e / o le proprietà semantiche :

link

per esempio:.

        var factorial = (Lambda)language.
            Evaluate
            (@"
                ( => ( n ) (
                        ? ( != n 0 )
                        ( * n ( this ( - n 1 ) ) )
                        1
                    )
                )
            ");

        var sw = new System.Diagnostics.Stopwatch();
        var n = 12;
        var r = 0;
        int k;
        sw.Start();
        for (k = 0; k < 10000; k++)
        {
            r = (int)factorial.Invoke(null, n);
        }
        sw.Stop();
        Console.WriteLine("{0}! = {1}", n, r);
        Console.WriteLine();
        Console.WriteLine("in {0} ms (for {1} times)", sw.ElapsedMilliseconds, k.ToString("0,0"));

'HTH,

    
risposta data 27.07.2016 - 03:04
fonte
0

Supponendo che tu conosca un po 'di Scheme (ad esempio hai letto SICP ) o Lisp, ti consiglio Queinnec's Lisp In Small Pieces libro. Spiega diverse varianti di interpreti e ampli Lisp-like; compilatori (incluso in bytecode o in C).

Leggi anche la programmazione linguistica Pragmatica di Scott, l'ultima Dragon Book , il manuale GC , Pierce's Tipi e amp; linguaggi di programmazione .

I am seeking information on how to go from a compiler to an interpreter.

Quindi, valutazione parziale (& proiezioni Futamura) e lo stile di passaggio continuo potrebbe essere rilevante.

    
risposta data 27.07.2016 - 06:51
fonte

Leggi altre domande sui tag