Linguaggi di programmazione

Un linguaggio di programmazione, in informatica, è un linguaggio formale che specifica un insieme di istruzioni che possono essere usate per produrre azioni su un dispositivo informatico

Questo è utilizzabile per il controllo del comportamento di una macchina formale o di un'implementazione di essa (tipicamente, un computer) ovvero in fase di programmazione di questa attraverso la scrittura del codice sorgente di un programma.

Linguaggio Macchina

I linguaggi macchina sono i più rudimentali; vengono espressi in codice binario e sono direttamente interpretabili dalla CPU per la loro immediata corrispondenza con i segnali elettrici con cui vengono tradotti.

Un programma scritto mediante un linguaggio macchina viene anche detto codice.

Un codice è un sistema di simboli attraverso i quali è possibile trasformare le informazioni in dati che la macchina è in grado di interpretare e di elaborare. Il microprocessore preleva le informazioni necessarie da un programma residente in memoria, lo decodifica ed esegue le istruzioni in esso contenute.

I codici alfanumerici utilizzano solo numeri e lettere. Un programma scritto in linguaggio macchina è espresso mediante un codice binario. Per una più agevole interpretazione da parte dell'operatore, il codice in genere rappresentato anche mediante il formato esadecimale, formato appunto dalle dieci cifre decimali e dalle lettere da A ad F.

Traduttori:

I traduttori sono programmi che consentono di passare da un linguaggio di natura diversa al linguaggio più adatto ad essere eseguito dalla macchina, realizzando così una funzione di traduzione. Possono venire classificati come segue:

  • compilatori;
  • interpreti;
  • assemblatori.


Linguaggio Compilato

L'espressione "linguaggio compilato" indica un linguaggio di programmazione implementato di solito tramite un compilatore (un traduttore che converte il codice sorgente in codice macchina), invece di un interprete (che esegue direttamente il codice sorgente).

Un programma compilato è generalmente autonomo, nel senso che non richiede che sia stato installato un secondo programma (l'interprete, appunto) per essere eseguito. Tuttavia, può richiedere che siano installati altri programmi e librerie per svolgere i propri compiti.
Un'altra conseguenza dell'assenza di interprete è il minor "peso" a tempo di esecuzione, in termini di tempo e memoria. Pertanto, un programma compilato risulta mediamente più veloce. Tuttavia, la differenza reale dipende dalle caratteristiche della macchina e dell'interprete utilizzato.


Linguaggio Interpretato

Un interprete, in informatica e nella programmazione, è un programma in grado di eseguire altri programmi a partire direttamente dal relativo codice sorgente scritto in un linguaggio di alto livello, senza la previa compilazione dello stesso (codice oggetto), eseguendo cioè le istruzioni nel linguaggio usato traducendole di volta in volta in istruzioni in linguaggio macchina del processore.


Che differenza c'è tra linguaggio compilato o linguaggio interpretato?

La compilazione traduce tutte le istruzioni di un programma in linguaggio macchina, creando un file eseguibile dal computer. L'interpretazione traduce ed esegue ogni singola istruzione del programma. Legge ed esegue il codice sorgente del programma senza creare un file oggetto eseguibile.

Assemblatori
Gli assemblatori (assembler) sono programmi che consentono il passaggio dal linguaggio Assembly al linguaggio macchina, ossia al codice binario.
Spesso il termine che indica il linguaggio a quello che indica il suo traduttore vengono confusi fra loro. Ciò peraltro favorito da particolari strumenti di lavoro spesso adottati, in cui la fase di stesura e quella della compilazione vengono eseguite nel medesimo ambiente di programmazione.


Il codice sorgente è il testo di un algoritmo di un programma. Il nome “sorgente” è dovuto al fatto che il codice rappresenta il punto di partenza di tutto il processo di esecuzione del programma. 

Il codice sorgente è scritto in un linguaggio di programmazione, nella pratica si parla di codici sorgenti anche per indicare i linguaggi di markup o altri testi scritti non in un linguaggio di programmazione.

Dal punto di vista strutturale, il codice sorgente è una sorta di algoritmo risolutivo: il programmatore, attraverso un editor di testo che appartiene a un ambiente di sviluppo integrato, scrive il codice tenendo conto della sintassi e del lessico del linguaggio di programmazione a cui fa riferimento.

Linguaggi di programmazione più comuni:
  • HTML (non linguaggio di programmazione in senso stretto)
  • JavaScript (non linguaggio di programmazione in senso stretto)
  • PHP  (non linguaggio di programmazione in senso stretto; lato server)
  • C, C++
  • Python
  • Perl
  • BASIC, esistono diverse versioni compilate e pseudo-compilate, come Turbo Basic e Visual Basic
  • Java

Classi di linguaggi

In generale esistono circa 2500 linguaggi di programmazione più o meno noti e diffusi. Questi in primis vengono classificati, a seconda del livello di astrazione a partire dal linguaggio macchina fin verso il linguaggio logico umano, in linguaggi a basso livello e ad alto livello (negli anni novanta si distinguevano anche quelli ad altissimo livello). A loro volta i linguaggi possono essere classificati in linguaggi compilati e interpretati come visto sopra. Normalmente i linguaggi vengono poi distinti in tre grandi famiglie basate sul paradigma di programmazione di riferimento: i linguaggi imperativi, quelli funzionali e quelli logici.

Imperativi

Nei linguaggi imperativi l'istruzione è un comando esplicito, che opera su una o più variabili oppure sullo stato interno della macchina, e le istruzioni vengono eseguite in un ordine prestabilito. Scrivere un programma in un linguaggio imperativo significa essenzialmente occuparsi di cosa la macchina deve fare per ottenere il risultato che si vuole, e il programmatore è impegnato nel mettere a punto gli algoritmi necessari a manipolare i dati. Le strutture di controllo assumono la forma di istruzioni di flusso (GOTO, FOR, IF/THEN/ELSE ecc.) e il calcolo procede per iterazione piuttosto che per ricorsione. I valori delle variabili sono spesso assegnati a partire da costanti o da altre variabili (assegnamento) e raramente per passaggio di parametri (istanziazione).

Tipici linguaggi imperativi:

  • APL
  • Assembly
  • ALGOL
  • B
  • BASIC
  • BCPL
  • C
  • COBOL
  • FORTRAN
  • Forth
  • Hot soup processor
  • PL/I
  • POP

Strutturati

La programmazione strutturata è una tecnica il cui scopo è di limitare la complessità della struttura del controllo dei programmi. Il programmatore è vincolato ad usare solo le strutture di controllo canoniche definite dal Teorema di Böhm-Jacopini, ovvero la sequenza, la selezione e il ciclo, evitando le istruzioni di salto incondizionato.

  • Ada
  • Fortran 90/95
  • Modula-2
  • Oberon
  • Pascal

Orientati ad oggetti

La programmazione a oggetti è basata su un'evoluzione del concetto di tipo di dato astratto caratterizzata da incapsulamento, ereditarietà, polimorfismo. Oltre a linguaggi specializzati che implementano completamente i principi di tale metodologia (come Smalltalk o Java), molti linguaggi moderni incorporano alcuni concetti della programmazione a oggetti.

  • Ada95
  • Attack
  • BETA
  • Clarion
  • CLOS
  • C++
  • C#
  • D
  • DataFlex
  • Delphi
  • Eiffel
  • Fortran 2003
  • Java
  • Linden Scripting Language
  • Modula-3
  • mShell
  • Objective C
  • OCaml
  • OpenGenera
  • PHP
  • Python
  • PowerBuilder
  • REALbasic
  • REBOL
  • Ruby
  • Scala
  • Scriptol
  • Simula
  • Smalltalk
  • Visual Basic
  • Visual Basic .NET

Funzionali

I linguaggi funzionali sono basati sul concetto matematico di funzione. In un linguaggio funzionale puro l'assegnazione esplicita risulta addirittura completamente assente e si utilizza soltanto il passaggio dei parametri. Tipicamente in tale modello il controllo del calcolo è gestito dalla ricorsione e dal pattern matching (l'azione di controllo della presenza di un certo motivo - pattern - all'interno di un oggetto composito), mentre la struttura dati più diffusa è la lista, una sequenza di elementi. Il più importante esponente di questa categoria è senz'altro il Lisp (LISt Processing).

  • Clarion
  • Clean
  • Clojure
  • Curry
  • Haskell
  • Lisp
  • Scala
  • Scheme
  • Standard ML
  • Caml
  • OCaml
  • C++11
  • F#

Dichiarativi (o logici)

Nei linguaggi logici l'istruzione è una clausola che descrive una relazione fra i dati: programmare in un linguaggio logico significa descrivere l'insieme delle relazioni esistenti fra i dati e il risultato voluto, e il programmatore è impegnato nello stabilire in che modo i dati devono evolvere durante il calcolo. Non c'è un ordine prestabilito di esecuzione delle varie clausole, ma è compito dell'interprete trovare l'ordine giusto. La struttura di controllo principale è rappresentata dal cut, che è detto rosso se modifica il comportamento del programma o verde se rende solo più efficiente il calcolo, che procede per ricorsione e non per iterazione. Le variabili ricevono il loro valore per istanziazione o da altre variabili già assegnate nella clausola (unificazione) e quasi mai per assegnamento, che è usato solo in caso di calcolo diretto di espressioni numeriche.

Affinché sia possibile usarli in un programma dichiarativo, tutti i normali algoritmi devono essere riformulati in termini ricorsivi e di backtracking; questo rende la programmazione con questi linguaggi un'esperienza del tutto nuova e richiede di assumere un modo di pensare radicalmente diverso, perché più che calcolare un risultato si richiede di dimostrarne il valore esatto. A fronte di queste richieste, i linguaggi dichiarativi consentono di raggiungere risultati eccezionali quando si tratta di manipolare gruppi di enti in relazione fra loro.

  • Curry
  • Mercury
  • Prolog

Linguaggi di Basso Livello

Il computer, come è noto, necessita per il suo funzionamento logico e elettrico di impulsi codificati nei due soli stati che esso è in grado di riconoscere. Ci si esprime quindi con termini livello alto e livello basso, di tensione, associabili ai valori logici 1 e 0. Un codice formato solo da tale tipo di simboli viene chiamato linguaggio macchina.

La lettura di un codice scritto in linguaggio macchina risulta in genere piuttosto difficoltosa. A ciò pone rimedio il linguaggio Assembly, che associa alle singole istruzioni del linguaggio macchina le abbreviazioni delle parole inglesi che indicano il compito da svolgere, costituendone così il codice mnemonico.

Ogni microprocessore possiede un proprio linguaggio a basso livello di tipo Assembly. Ciò evidentemente ostacola la possibilità di poter usare programmi scritti per un dato processore su di un altro dispositivo. per tipi omogenei di microprocessori, costruiti dalla stessa ditta, è tuttavia possibile riconoscere variabili, costanti, e istruzioni comuni. Nello sviluppo dei linguaggi si fa inoltre in modo che quelli usati per un dato processore conservino la loro validità anche per i modelli più evoluti. Ciò non è però sempre valido nel caso contrario. Alla sigla mnemonica fanno eventualmente seguito altre informazioni che indicano alla CPU quali sono i registri, gli indirizzi di memoria o i dati interessati. Poiché normalmente l'istruzione ha il compito di elaborare un qualche elemento prelevato da una determinata sorgente e porre il risultato ottenuto in una certa zona di destinazione, le parti che completano il mnemonico dell'istruzione vengono dette operando destinazione e operando sorgente.

La sigla mnemonica viene anche detta operatore.

operando destinazione <--- operando sorgente

Per caricare un dato in un registro o in memoria si può utilizzare ad esempio la sigla mnemonica MOV (dall'inglese move = muovere) oppure LD (Load, caricare), per sommare ADD, per sottrarre SUB, e così via.

In un istruzione l'operatore deve essere sempre presente, mentre può mancare o l'operando destinazione o l'operando sorgente o entrambi. E' sottinteso comunque che tali elementi vengono resi espliciti nella traduzione in codice macchina dell'istruzione. Per l'esecuzione di un programma scritto in Assembly occorre procedere attraverso le seguenti fasi:

  1. stesura;
  2. assemblaggio;
  3. ottimizzazione;
  4. analisi.

Stesura

Per effettuare la stesura del programma è necessario seguire le regole ortografiche previste dal linguaggio legato al particolare processore scelto. Occorrerà quindi verificare la correttezza del programma nel suo insieme, mediante l'operazione detta debug. Per la scrittura materiale del programma Assembly può venire impiegato un comune editor di testi che produca un file in formato ASCII, come ad esempio il NotePad di Windows. Il programma sorgente viene in genere salvato su disco con estensione ASM:

Assemblaggio

Il programma sorgente deve essere tradotto utilizzando un assemblatore, come per esempio Microsoft Assembler o Turbo Assembler della Borland. Si ottiene così un nuovo programma chiamato programma oggetto, con estensione OBJ. Su questo occorre ancora procedere per il collegamento degli indirizzi. E' necessario quindi far ricorso ad uno strumento software detto linker, come per esempio Link.exe o Tlink.exe, che risolva appunto tale tipo di problemi. Il risultato dell'operazione è un file con estensione EXE, direttamente eseguibile. 

Ottimizzazione

Una volta assemblato il programma è pronto per l'esecuzione. Il fatto che il programma risulti in grado di funzionare non garantisce tuttavia risultati sempre accettabili. La fase di ottimizzazione, eseguita con il supporto di appositi strumenti software, serve ad individuare le istruzioni troppo elaborate e a procedere alla loro semplificazione ottenendo tempi più rapidi di esecuzione.

Analisi

Per una riuscita pienamente soddisfacente è a volte necessaria un'ulteriore fase di verifica, chiamata analisi di esecuzione. Essa consiste nell'individuare, tramite un programma detto profiler, la funzionalità degli algoritmi, i tempi di esecuzione e di ripetizione delle istruzioni, le chiamate a sottoprogrammi, tutto quanto insomma può costituire un rallentamento e una inefficiente gestione delle risorse del sistema. A questo punto il programma è finalmente pronto per eseguire i compiti assegnati con la necessaria efficacia.


Ultime modifiche: giovedì, 28 ottobre 2021, 22:21