Comments
Transcript
Analisi e sviluppo di un framework per supportare
FACOLTA’ DI SCIENZE MM.FF.NN Corso di Laurea Specialistica in Scienze dell'Informazione _______________________________________________________________________ Analisi e sviluppo di un framework per supportare modelli di programmazione visuale e iconica Tesi di Laurea Specialistica di Relatore Dott. Guido Averna Ch. Prof. Domenico Tegolo Matricola: 0528662 ANNO ACCADEMICO 2011 - 2012 1 Ringraziamenti Questo lavoro è frutto dei suggerimenti e dei tanti spunti di riflessione ricevuti nel corso degli studi. Un ringraziamento sentito va al Professore Domenico Tegolo, fonte di ispirazione e preziosa guida lungo le linee portanti della ricerca e a coloro che mi hanno sostenuto lungo il percorso, e a tutti i Professori del Corso di Laurea Specialistica,che mi hanno permesso di vivere questa splendida esperienza. 2 C'è una forza motrice più forte del vapore, dell'elettricità e dell'energia atomica: la volontà. Albert Einstein 3 Indice Introduzione Capitolo I Linguaggi di programmazione visuale: stato dell’arte pag. 8 1.1 Ragioni del linguaggio visuale pag. 9 1.2 Scopo della ricerca dei linguaggi di programmazione iconica pag. 11 1.3 Aspetti cognitivi pag. 12 1.3.1 Manipolazione diretta pag. 13 1.3.2 Visualizzazione delle informazioni pag. 13 1.3.3 Visualizzazione del software pag. 14 1.3.4 Rappresentazione e ragionamento diagrammatico pag. 14 1.4 Problemi nella rappresentazione iconica pag. 15 1.4.1 Icone e simboli pag. 16 1.4.2 Semantica e sintassi pag. 17 1.4.3 Caratteristiche complesse pag. 17 1.4.3.1 Concretezza pag. 18 1.4.3.2 Immediatezza pag. 18 1.4.3.3 Chiarezza pag. 19 1.4.3.4 Immediato feedback visuale pag. 19 1.5 Esempi di software di programmazione visuale pag. 19 1.5.1 Labview pag. 20 1.5.2 UML pag. 23 Capitolo II Principali costruitti, tipi, array e strutture dati pag. 28 4 2.1 Definizione di costrutto pag. 28 2.2 Costrutti principali pag. 29 2.2.1 Dichiarazione di Costanti pag. 30 2.2.2 Dichiarazione di Variabili pag. 31 2.2.3 Assegnazione pag. 32 2.2.4 Condizione pag. 33 2.2.5 Sequenze pag. 36 2.2.6 Cicli pag. 37 2.2.6.1 Ciclo For pag. 37 2.2.6.2 Ciclo While pag. 38 2.2.6.3 Ciclo Repeat .. Until e Do .. While pag. 39 2.2.6.4 Considerazioni sui cicli pag. 40 2.2.7 If .. Then .. Else pag. 41 2.2.8 Break, Continue e Return pag. 42 2.2.8.1 Break pag. 43 2.2.8.2 Continue pag. 43 2.2.8.3 Return pag. 43 2.2.9 Switch .. Case pag. 44 2.2.10 Procedure e Funzioni pag. 47 2.2.10.1 Procedura pag. 48 2.2.10.2 Funzione pag. 50 2.3 Tipi pag. 52 2.3.1 Tipi primitivi pag. 53 2.3.2 Tipi di enumerazioni pag. 54 2.3.3 Array pag. 57 2.3.4 Strutture pag. 58 2.4 Analisi finale pag. 59 5 Capitolo III Sviluppo di un linguaggio di programmazione iconico pag. 60 3.1 Sviluppo del Framework pag. 60 3.2 Sviluppo del linguaggio iconico dal punto di vista concettuale pag. 62 3.2.1 Implementazione concettuale del flusso pag. 62 3.2.2 Rappresentazione visiva dei costrutti principali pag. 65 3.2.2.1 Colore del contorno pag. 65 3.2.2.2 Colore del riempimento pag. 67 3.2.2.3 Forme delle icone pag. 67 3.2.2.4 Testo delle icone pag. 70 3.3 Esplicitazione del codice sorgente mediante l’uso delle icone pag. 71 3.4 Integratore iconico con un Parser XML pag. 72 3.5 Indicizzatore di librerie generiche pag. 73 3.5.1 Regular Expression pag. 73 3.6 Analisi finale pag. 78 Capitolo IV Implementazione del linguaggio di programmazione iconico pag. 80 4.1 Sviluppo del Linguaggio pag. 80 4.1.1 Cenni sull’ereditarietà e sul polimorfismo pag. 81 4.1.2 Cenni di caratteristiche avanzate del linguaggio Delphi pag. 82 4.1.3 Gli Eventi pag. 83 4.1.4 Sovrascrittura delle funzioni e procedure ereditate pag. 84 4.1.5 Visibilità di proprietà e metodi e semplici tecniche di Hacking pag. 86 4.2 Implementazione del Framework Iconico pag. 89 4.2.1 Classe TForme pag. 89 4.2.2 Classe TFigura_Start pag. 99 4.2.3 Classe TFigura_Dato pag.100 6 4.2.3.1 Classe TTipo_Dato pag.102 4.2.3.2 Classe TDato_Matrice pag.104 4.2.4 Classe TFigura_Ciclo pag.106 4.2.4.1 Classe TCondizione pag.108 4.2.5 Classe TFigura_If_Then_Else pag.109 4.2.6 Classe TFigura_Blocco pag.110 4.2.7 Classe TFigura_Break_Continue_Exit pag.111 4.2.8 Classe TFigura_Switch pag.112 4.2.9 Classe TFigura_Assegnazione pag.113 4.2.10 Classe TFigura_Funzione pag.115 4.2.11 Classi TFigura_Label, TFigura_Goto, TFigura_Return, TFigura_Begin, TFigura_End pag.116 4.3 Implementazione del flusso grafico: classe TLinker pag.116 4.4 Integrazione del parser XML pag.119 4.4.1 Classe TXML_Progetto pag.119 4.4.2 Classe TXML_File pag.121 4.4.3 Classe TXML_Funzione pag.123 4.5 Implementazione sintetica dell’indicizzatore di librerie pag.124 4.5.1 Classe TC_Sorgente pag.125 4.5.2 Classe TC_Metodi pag.126 4.6 Implementazione del Text Editor pag.128 4.7 Implementazione delle caratteristiche del framework pag.131 Conclusioni pag.134 Bibliografia pag.135 7 Introduzione Dallo scorso secolo, si è palesato un crescente interesse riguardo all’interazione Uomo-Macchina. Questo ha portato a una maggiore attenzione circa la possibilità di programmare le macchine e sviluppare nuovi software attraverso un linguaggio iconico, ci si è quindi domandati quale potesse essere una rappresentazione iconico in grado di sfruttare i punti di forza delle immagini al fine di sviluppare algoritmi e programmi. In questo lavoro si analizzeranno, dunque, gli aspetti chiave, utili a comprendere quali icone possano meglio essere comprensibili, fornendo un’immediata associazione tra loro e con i principali costrutti e dati del linguaggio di programmazione C. Si analizzerà la dichiarazione di tali strutture ponendo le basi per implementare un framework iconico. Verrà poi sviluppato concettualmente il framework stesso, soffermandosi sui vari aspetti, e sulle caratteristiche grafiche che le icone dovrebbero possedere affinché mostrino un chiaro linguaggio, che possa essere utilizzato dai professionisti ma al contempo anche dai principianti. Mediante l’uso del linguaggio Delphi si svilupperanno, infine, le classi e gli oggetti che rendono disponibile tale linguaggio, soffermandosi sui dettagli implementativi e spiegando come tali classi interagiscano tra loro. Si giungerà alla conclusione analizzando l’operato del processo, e la molteplicità dei suoi possibili utilizzi pratici. 8 Capitolo I LINGUAGGI DI PROGRAMMAZIONE VISUALE: STATO DELL’ARTE 1.1 Ragioni del linguaggio visuale Il linguaggio, in generale, può essere definito come una formalizzazione di schemi concettuali e di pensieri che l’essere umano riesce ad elaborare. Questi schemi o pensieri vengono riconosciuti ed interpretati dal cervello, e converti in rappresentazioni visuali. Molte volte queste rappresentazioni sono talmente radicate nella mente da associarsi irrimediabilmente ad immagini (Arnheim, 1969) e ad essere associati a linguaggi visuali od iconici. La facilità di comprendere le rappresentazioni iconiche è un fattore significativo nell’area dei linguaggi visuali (Blackwell, 1996). Tuttavia, vi è una notevole difficoltà a formalizzare i linguaggi visuali a causa di svariate variabili in gioco. La progettazione e l'analisi di linguaggi di programmazione sono sempre stati guidati da questioni di elasticità e di efficienza, non dall'usabilità o la comprensibilità. Inoltre, le proprietà cognitive di una linguaggio sono in genere verificate solo dopo la loro progettazione e il loro uso. Il ruolo centrale dei 9 linguaggi visivi consiste nell’affermare il proprio ruolo come strumento per la comunicazione e l'interazione, fornendo inoltre un’interfaccia Uomo – Macchina. Ciò implica che la teoria dei linguaggi visivi richiede una conoscenza più ampia rispetto alla teoria dei linguaggi di programmazione e in generale alla teoria dei linguaggi. Il motivo principale dell’uso dei linguaggi iconici è dovuta all’interazione del linguaggio visivo Uomo – Macchina comprendendo una vasta classe di approcci che sono stati oggetto di ricerca della comunità scientifica. Tali linguaggi facilitano la costruzione di immagini mentali e inoltre permettono una più facile ed immediata formalizzazione cognitiva. La visualizzazione conduce, inevitabilmente, a diversificare l’uso grafico dei simboli e dei linguaggi in diversi campi: I linguaggi visivi: sono tutti quei linguaggi dati dalla rappresentazione visuale adibiti alla interfaccia Uomo – Uomo o Uomo – Macchina. In questi linguaggi rientrano i linguaggi naturali e iconici. La programmazione testuale: usata per comunicare dati, istruzioni ed operazioni al computer. In questo gruppo di linguaggi rientrano i ben noti e consolidati linguaggi C e Pascal e le rispettive estensioni. I linguaggi di programmazione iconica: nei quali le immagini, o icone, rappresentano visivamente le entità, l’alfabeto o i simboli del linguaggio, e ad ognuno di essi viene associato un particolare significato o una ben determinata azione. In questa famiglia di linguaggi ricadono Labview e l’UML, Unified Modeling Language. Tali linguaggi sono anche conosciuti come VPL, Visual Programming Language. Software di visualizzazione: i quali servono a raffigurare visivamente rappresentazioni atte a trasmettere all’uomo un’insieme di proprietà statiche o 10 dinamiche di software, inclusi codici, dati e algoritmi. Esempi di questi software sono ambienti di sviluppo software o IDE, Integrated Development Environment. Algoritmo di animazione: i quali altro non sono che immagini dinamiche e visive che riproducono il funzionamento degl’algoritmi sui vari dati. Rappresentazioni diagrammatiche: raffigurazioni che forniscono informazioni descrittive senza rappresentare una vera e propria entità. Un esempio è la ben nota rappresentazione concettuale tramite i Diagrammi a blocchi, universalmente conosciuta ed ampiamente usata. Nel prosieguo si riferirà ai linguaggi visuali come ai linguaggi di programmazione visuale. 1.2 Scopo della ricerca dei linguaggi di programmazione iconica La ricerca della teoria dei linguaggi visuali tenta di liberare i programmatori e gli utenti finali dai vincoli della programmazione testuale e simbolica, fornendo un insieme di strumenti iconici utili, intuitivi e facilmente utilizzabili. Durante gli anni, si sono sviluppati svariati e diversi linguaggi iconici, ognuno seguendo una propria e differente filosofia atta a formalizzare un appropriato campo di studio. Ad esempio i fisici, al fine di ottenere una facile comprensione del fenomeno descritto, usano i Diagrammi di Feynman, che permettono di tradurre una interazione in un semplice schema; i matematici usano i Diagrammi Commutativi, ovvero dei diagrammi che comprendono svariate entità e 11 morfismi tra di loro tali che per ogni coppia di oggetti ogni percorso che li collega produce la stessa applicazione finale; gli informatici usano diagrammi iconici rappresentanti strutture dati tra loro collegate attraverso delle frecce, per indicare le relazioni che intercorrono tra le varie strutture ed entità. 1.3 Aspetti cognitivi I linguaggi visuali offrono un approccio completamente differente alla classica programmazione. Ciò porta a concepire un nuovo modo di programmare, e a nuovi aspetti cognitivi che derivano da questo approccio. In base al tipo di approccio iconico utilizzato per la programmazione o la progettazione dei vari algoritmi, l’utente finale sfrutta un modo di pensare che non segue necessariamente l’impostazione classica. Gli approcci possono essere di tipo: Manipolazione diretta Visualizzazione delle informazioni differente Visualizzazione delle software differente Rappresentazione e ragionamento diagrammatico Simulazioni grafiche 12 1.3.1 Manipolazione diretta Questo genere di approccio fornisce agli utenti degli strumenti atti ad eseguire delle azioni direttamente sulle strutture dati, interagendo in maniera visuale con gli oggetti. Un esempio classico è lo spostamento di un file da una cartella ad un’altra trascinando il file. Con tale approccio si creano e si innescano schemi cognitivi atti a fornire una rappresentazione dell’azione diretta su una struttura dati, fornendo benefici di immediatezza delle esecuzioni delle istruzioni ed un’associazione tra immagine-azione. 1.3.2 Visualizzazione delle informazioni Per l’uomo, la rappresentazione visuale di una struttura dati è maggiormente comprensibile rispetto alla tipizzazione testuale classica di una struttura dati. Gli oggetti iconici descrivono i dati in un modo maggiormente comprensibile e familiare all’uomo, sebbene la descrizione testuale sia tecnicamente equivalente. Tale metodologia, permette di sottolineare e rendere maggiormente visibile quelle rappresentazioni dei dati che sono nascoste, fornendo una chiara ed immediata rappresentazione del concetto o azione da esprimere. Ad esempio, si consideri il linguaggio HTML. L’Hyper Text Markup Language, seppur un linguaggio di formattazione, se usato in concomitanza con un qualunque browser fornisce un’interazione con l’utente veramente notevole. Ad esempio, l’uso del suo oggetto, o tag, “IMG”, in versione testuale fornisce 13 un’informazione scarsamente comprensibile all’utente, ma tradotto in maniera visuale, dal browser, fornisce come oggetto un’immagine, la quale offre un’informazione maggiore, se non, addirittura, completamente differente. 1.3.3 Visualizzazione del software La visualizzazione del software risulta essere maggiormente comprensibile, in quanto le strutture dati e il flusso del programma appaiono definite attraverso grafi e diagrammi di flusso, i quali forniscono immediatamente ed intuitivamente il comportamento del programma e delle sue strutture. Tale metodo, è l’inverso dell’analisi di un linguaggio di programmazione visuale. Così si genera una rappresentazione che fornisce visivamente le stesse informazioni circa la sintassi e la semantica utilizzate, ma in un modo più comprensibile all’occhio umano tale da rende l’immediatezza della sua struttura logica. 1.3.4 Rappresentazione e ragionamento diagrammatico In molti casi, nella programmazione testuale, è richiesta una maggiore analisi del programma quando bisogna definire le relazioni e le proprietà delle strutture dati. Talvolta, queste relazioni sono talmente implicite da richiedere estremamente dettagliata la quale richiede tempi tecnici eccessivamente onerosi 14 per l’utente. Nella rappresentazione diagrammatica, le relazioni e le proprietà vengono esplicitate (Larkin, Simon, 1987). Le rappresentazioni visuali forniscono un più intuitivo ragionamento, acuendo la conoscenza di base (Narayanan, Suwa, Motoda, 1994). Questo rende più facile la comprensione delle implicazioni logiche tra le varie icone (Larkin, 1989). Inoltre, questo migliora la comprensione circa la possibile modifica di queste proprietà e dei loro effetti sugli oggetti fisici (Narayanan, Suwa, Motoda, 1995), ovvero delle istanze delle entità. In questa maniera, è più facile immaginare l’effetto delle modifiche sul sistema simulando preventivamente il loro comportamento grafico. 1.4 Problemi nella rappresentazione iconica La differenza tra icone e simboli è di importanza fondamentale nello sviluppo di un linguaggio visivo, in quanto persone di differenti nazionalità che parlano diverse lingue hanno necessità di sfruttare uno strumento che possa essere compreso universalmente. Inoltre, ulteriori problemi sono sia lo stile dal punto di vista grafico che i meccanismi di composizione tra gli oggetti. 15 1.4.1 Icone e simboli Charles Peirce caratterizzò, nel 1955, la differenza sostanziale che intercorre tra le icone e i simboli: “Un’icona è un segno che si riferisce ad un oggetto il quale denota meramente la virtù dei propri caratteri” e “Un simbolo è un segno che si riferisce ad un oggetto il quale denota la virtù di un processo, usualmente un’associazione di idee generali” (Peirce in Buchler, 1955). In altre parole, il significato cognitivo di un’icona e indipendente dalla persona che la vuole interpretare. Questa indipendenza è la caratteristica che rende il linguaggio visuale universalmente utilizzato. Ma vi sono varie difficoltà e limitazioni per relazionare rappresentazioni iconiche a significati complessi. Gli psicologi trovarono diverse dipendenze culturali anche a livello percettivo. Le persone hanno una differente percezione dei simboli e in alcuni contesti non riconoscono gli oggetti allo stesso modo. La percezione dipende dal contesto oltre che dall’immagine, e il ruolo che possiede un particolare segno, icona o simbolo, dipende dalla sua relazione con interpretazione ed è affine alla sua caratteristica intrinseca (ad esempio un colore o una forma). Inoltre è associata alla relazione del mondo reale con l’oggetto, ed un’associazione artificiale, come può essere una convenzione linguistica. Molto spesso è plausibile creare una successione sempre più stilizzata dei segni, cominciando con un’immagine realistica e finendo con un simbolo astratto, che permette di comprendere un’associazione simbolica astratta. Inoltre, in alcuni casi una rappresentazione iconica può essere presa come un’estrema rappresentazione teorica, e i concetti astratti possono essere comunicati mediante l’uso di poche icone. Ad esempio i vari linguaggi usati dagl’uomini si sono evoluti continuamente: uno di questi è il linguaggio 16 cinese che si è evoluto da una rappresentazione figurativa esplicita ad una raffigurazione altamente stilizzata, così anche le icone possono cambiare forma da immagini dettagliate a simboli astratti sui computer, ma con tempistiche estremamente più veloci. 1.4.2 Semantica e sintassi Un secondo problema è lo sviluppo di una semantica e di una sintassi dei linguaggi visivi che siano idonee ed adeguate, oltre alla manipolazione diretta degli oggetti. Questo non è un modo di programmare dei linguaggi tradizionali, e a secondo del framework implementato, può essere più o meno ostico e poco intuitivo realizzare caratteristiche del linguaggio iconico atte a supportare tali funzionalità. La ricerca, che punta a supportare i meccanismi implementativi necessari per lo sviluppo di tali caratteristiche dei linguaggi non tradizionali, è ancora, però, poco praticata e diffusa. 1.4.3 Caratteristiche complesse Un linguaggio visuale deve avere caratteristiche complesse da sviluppare, quali la concretezza, l’immediatezza, la chiarezza, e un immediato feedback visuale. Tali caratteristiche devono essere implementate per sviluppare un linguaggio visuale. 17 1.4.3.1 Concretezza La concretezza esprime specifici aspetti del programma, usando istanze prestabilite, al fine di esplicitare i tratti semantici che delineano il comportamento che si intende produrre. E' un processo che avviene tramite l'utilizzo di determinati oggetti o valori scelti per l'immediata corrispondenza ideologica. 1.4.3.2 Immediatezza In termini implementativi, questa caratteristica può essere descritta come una, breve, distanza che intercorre uno scopo e l’azione proposta per ottenere lo scopo, ma questa è direttamente collegata alla manipolazione diretta degli oggetti. Come puntualizzano Green e Petre, la programmazione richiede una mappatura tra un problema reale e problema computazionale, più vicino è il problema computazionale al problema reale, più facilmente lo si potrà risolvere. Un esempio è il manipolare un oggetto per specificare il suo cambiamento di posizione, ovvero usare il movimento per specificare il movimento, invece di usare una funzione sulle coordinate dello schermo per specificarlo da esempio. 18 1.4.3.3 Chiarezza Alcuni aspetti della semantica sono esplicitati solo se sono direttamente affermati, sia testualmente che visivamente, senza una richiesta dello sviluppatore. Un esempio è la capacità di un linguaggio visuale di fornire visivamente le relazioni del flusso dei dati mediante l’uso di archi tra gli oggetti del programma. In un linguaggio testuale, questo è solo uno strumento esterno all’ide che può essere utilizzato, mentre in un linguaggio visuale può essere parte della sintassi o una caratteristica automatica dell’ambiente di sviluppo. 1.4.3.4 Immediato feedback visuale Questa si riferisce alla visualizzazione automatica degli effetti dei programmi di linguaggi testuali. Tanimoto creò il termine vitalità, che cataloga l’immediatezza del feedback semantico che è automaticamente fornito durante il processo di editing di un programma. Un esempio è la caratteristica di ricalcolo automatico di un foglio di calcolo. 1.5 Esempi di software di programmazione visuale Negli anni sono stati implementati svariati linguaggi visuali, sia software che standard di linguaggi visuali. Di seguito vengono forniti due casi, uno di un 19 software di fama internazionale e l’altro di un linguaggio divenuto uno standard per molti casi. 1.5.1 Labview Il LabVIEW (abbreviazione di Laboratory Virtual Instrumentation Engineering Workbench) è un ambiente di sviluppo integrato per il linguaggio di programmazione iconico creato dalla National Instruments. A causa di tale particolarità, questo linguaggio grafico viene chiamato Linguaggio G, Graphic Language. Un programma o sottoprogramma G, denominato VI (Virtual Instrument), non esiste sotto forma di testo, ma può essere salvato solo come un file binario, opportunamente codificato, visualizzabile e compilabile solo da LabVIEW. La definizione di strutture dati ed algoritmi avviene con icone e altri oggetti grafici, ognuno dei quali contiene e fornisce funzioni diverse, uniti da linee di collegamento (wire), in modo da formare uno schema che si avvicina molto ad un diagramma di flusso. Tale linguaggio viene definito dataflow (flusso di dati) in quanto la sequenza di esecuzione è definita e rappresentata dal flusso dei dati stessi attraverso gli archi direzionali che collegano i blocchi funzionali. Poiché i dati possono anche scorrere in parallelo attraverso blocchi e archi non consecutivi, il linguaggio realizza spontaneamente il multithreading senza bisogno di esplicita gestione da parte del programmatore. Il progetto LabVIEW nasce nel 1983 dalla necessità della National Instruments di disporre di un software grafico, con il quale testare rapidamente gli apparati hardware prodotti da tale industria statunitense. 20 Già nel 1986 è resa pubblica la versione 1 del software compatibile con i sistemi Macintosh. Nel gennaio del 1990 viene pubblicata la versione 2, gli aggiornamenti sul software rendono la velocità di esecuzione della versione 6 paragonabile ai programmi compilati in Ansi C. Il mese successivo in virtù dell'innovatività dell'approccio grafico alla programmazione, viene pubblicato il brevetto dal US Patent Office. Infine nel settembre 1992 ne viene sviluppata una versione multipiattaforma, cioè per Microsoft Windows, Mac OS e SunOS. In seguito venne supportato anche Linux. La versione 8.0, pubblicata nel 2005, introduce per la prima volta anche il supporto per la programmazione a oggetti. Nell'ambiente di sviluppo, i VI (Virtual Instruments) constano di tre componenti principali: il pannello frontale lo schema a blocchi il riquadro connettori Il pannello frontale costituisce l’interfaccia utente, dove è possibile inserire variabili, costanti, stringhe, array, controlli ed indicatori, pulsanti, termometri ed altri oggetti funzionali e facilmente identificabili. Questi costituiscono la parte visiva degli oggetti. Questi oggetti rappresentano delle vere e proprie classi visuali che, durante la storia di sviluppo del programma, forniscono all’utente molteplici caratteristiche più o meno complesse. Lo schema a blocchi rappresenta il vero e proprio lato funzionale del linguaggio. Con esso è possibile fornire associazioni tra gli oggetti ed implementare la logica di funzionamento del progetto o dell’applicativo che si 21 intende realizzare. Per l’implementazione vengono messi ulteriori oggetti che identificano sia istruzioni della logica di implementazione classica, sia funzioni e procedure già implementate, che in molti casi fanno si che si possa abbattere il tempo di sviluppo del programma oltre a fornire un valido aiuto per implementare funzioni più o meno complesse. Oltre ad essere un ambiente integrato, Labview è anche un compilatore a 32 e 64 bit. Si possono dunque creare eseguibili e DLL, Dynamic Link Library. Per usare tali eseguibili e DLL non occorre un'installazione di LabVIEW, ma è necessario che sul computer di destinazione sia installato almeno il run-time engine di LabVIEW. 22 Fig. 1.1 Esempio di pannello frontale e schema a blocchi in LabView 1.5.2 UML L’UML, ovvero l’Unified Modelling Language, è un linguaggio grafico basato sul concetto dei diagrammi a flussi. Si tratta di un linguaggio di modellazione usato per capire e descrivere le caratteristiche di un nuovo sistema o di uno 23 esistente e quindi atto alla rappresentazione degli shcemi. Il punto di forza dell’Unified Modeling Language consiste nel fatto che il processo di disegno del sistema può essere effettuato in modo tale che i clienti, gli analisti, i programmatori e chiunque altro sia coinvolto nel sistema di sviluppo possa capire ed esaminare in modo efficiente il sistema e prendere parte alla sua costruzione in modo attivo. L’UML nasce in seguito all’evoluzione dei linguaggi e approcci alla modelazione object oriented. In quel periodo, furono implementati svariati modelli e si sviluppò una vera e propria "guerra dei metodi" tra progettisti, sviluppatori e organizzazioni che tentarono di imporre il proprio modello di sviluppo, in quanto non era stato accettato alcun modello quale standard universale per la modellazione dei software. Nel 1994 due esperti di modellazione della Rational Software Corporation, Grady Booch e James Rumbaugh,unificarono i propri metodi, Booch e OMT (Object Management Technique), , entrambi ricercatori presso Rational Software. Nel 1995, il gruppo si allargò includendo anche Ivar Jacobson con il suo OOSE (Object Oriented Software Engineering), in seguito alla vendita della sua compagnia Objectory alla Rational. l'OMG raccolse tutti i principali metodologisti del settore in un incontro internazionale per discutere della notazione unificata.. Nel 1996, Booch, Rumbaugh e Jacobson furono incaricati da Rational di dirigere la creazione dell’Unified Modeling Language.In quest’anno i tre sviluppatori rilasciarono le versioni 0.9 e successivamente 0.91 dell’UML, quest’ultima fu ben accolta dalla comunità internazionale e dall’OMG (Object Management Group), e al progetto e grandi organizzazioni si unirono a Rational per proseguirlo, ad esempio Digital, Hewlett-Packard, IBM, Microsoft, Oracle e 24 Unisys.. Nel 1997, a seguito della formazione di questo grande gruppo, nacque l’UML versione 1.0. Un modello UML è costituito da: Viste: mostrano i diversi aspetti del sistema per mezzo di un insieme di diagrammi. Diagrammi: permettono di descrivere graficamente le viste logiche. Elementi del modello: concetti che permettono di realizzare vari diagrammi, ad esempio: classi, packages, oggetti, etc. Lo strato più esterno dell’UML è costituito dalle seguenti viste: Use Case View , o Vista dei casi d'uso, utilizzata per analizzare i requisiti utente. Obiettivo di questo livello di analisi è studiare il sistema considerandolo come una scatola nera. Design View, o Vista di progettazione, descrive come le funzionalità del sistema devono essere realizzate; in altre parole analizza il sistema dall'interno (scatola trasparente). Implementation View, o Vista di implementazione, descrive i packages, le classi e le reciproche dipendenze. Process View, o Vista dei processi, individua i processi e le entità che li eseguono sia per un utilizzo efficace delle risorse, sia per poter stabilire l'esecuzione parallela degli oggetti. 25 Deployment View, o Vista di sviluppo, mostra l'architettura fisica del sistema e definisce la posizione delle componenti software nella struttura stessa. I diagrammi sono di svariati tipi, ognuno dei quali descrive concetti diversi dagl’altri. A titolo esemplificativo: Class Diagram, o Diagramma di Classe, consente di descrivere tipi di entità, con le loro caratteristiche e le eventuali relazioni fra questi tipi. Object Diagram, o Diagramma d’Oggetto, descrive un sistema in termini di oggetti e relative relazioni. Statechart Diagram, o Diagramma di Stato, descrive il comportamento di entità o di classi in termini di stato, ovvero un automa a stati finiti. Activity Diagram, o Diagramma di Attività, definisce le attività da svolgere per realizzare una data funzionalità. Sequence Diagram, o Diagramma di Sequenza, desacrive uno scenario, ovvero una sequenza di azioni in cui tutte le scelte sono state già effettuate Communication Diagram, o Diagramma di Comunicazione, descrive l'interazione fra più partecipanti alla realizzazione di una certa funzionalità. Component Diagram, rappresenta la struttura interna del sistema software modellato in termini dei suoi componenti principali e delle relazioni fra di essi. 26 Deployment Diagram, descrive un sistema in termini di risorse hardware, dette nodi, e di relazioni fra di esse. Composite Structure Diagram, consente la rappresentazione della struttura interna di classi e altri componenti software. Gli elementi del modello sono le icone utilizzate nei vari diagrammi. L’UML è un linguaggio molto più complesso e sofisticato di quanto detto, anche in ragione dell’apporto di tutte le grandi organizzazioni che hanno partecipato al progetto. Fig 1.2 Esempio di State Chart Diagram 27 Capitolo II PRINCIPALI COSTRUTTI, TIPI, ARRAY E STRUTTURE DATI 2.1 Definizione di costrutto Ogni linguaggio di programmazione, sia esso testuale sia iconico, presenta una serie di costrutti fondamentali e non, tipi e strutture dati. E’ noto che i linguaggi e le scritture sono basate su un sistemi iconici. Le icone dunque rappresentano le micro strutture della macro struttura con cui è strutturato un linguaggio. Il costrutto, dunque, è la struttura che si da ad un'idea per renderla esprimibile attraverso un sistema iconico. Un prototipo di linguaggio di programmazione testuale presenta una propria formalizzazione del costrutto. Ad esempio, una tipica assegnazione di un metalinguaggio AB+C 28 è un costrutto che assegna ad una variabile A il risultato di un operatore somma tra altre due variabili B e C, ovvero il simbolo A è legato ed associato al risultato dell’operatore somma di altrettanti due simboli B e C. 2.2 Costrutti principali I principali costrutti presenti nei linguaggi di programmazione, sia testuale che iconico sono: Dichiarazione di Variabili e Costanti Assegnazione Espressione e Condizione Cicli: For, While, Repeat .. Until e Do .. While If .. Then .. Else Break, Continue, Return Switch .. Case Il richiamo di Procedure e Funzioni Nel prosieguo si discuterà sulla formalizzazione dei costrutti in maniera generica, su un metalinguaggio e basato sul linguaggio C, Delphi o Pascal e di un linguaggio di programmazione iconica. 29 2.2.1 Dichiarazione di Costanti La costante è un simbolo a cui è legato, generalmente, un valore fissato nel tempo. Ogni costante, o variabile, deve essere dichiarata prima di poter essere usata, questo in quanto il simbolo rappresentato dalla costante, o variabile, deve essere conosciuto precedentemente dal compilatore e, quindi, dall’applicativo stesso. Una tipica dichiarazione di un generico metalinguaggio è del tipo: const tipo_di_dato A espressione dove la parola chiave const identifica che il simbolo A è una costante, tipo_di_dato è il tipo di dato al quale A afferisce, ovvero A è una istanza di tipo_di_dato, infine espressione è il valore che sarà assegnato ad A, questo può anche essere un’espressione molto articolata. Nel linguaggio C la dichiarazione è molto simile, cambia solo la sintassi: const tipo_di_dato A espressione Questa dichiarazione può essere inserita in qualunque sezione di una funzione del linguaggio C o anche al di fuori delle funzioni. Essa può anche essere inserita come parametro ad una funzione. Nel linguaggio Delphi la dichiarazione di una costante non può essere inserita in qualunque parte del sorgente, ma trova la sua locazione o tra la specifica delle 30 unità utilizzate e le istruzioni da eseguire oppure si trova tra la dichiarazione di una funzione e l’inizio delle stesse. Un linguaggio di programmazione iconica deve essere in grado di poter dichiarare una costante, inserendo opportunamente la dichiarazione all’interno del codice. 2.2.2 Dichiarazione di Variabili Sia in un metalinguaggio che in C la dichiarazione di una variabile avviene similmente come nella dichiarazione di una costante. Quindi, la variabile può essere oltre che dichiarata anche inizializzata con un valore. Nel linguaggio Delphi la dichiarazione di una variabile avviene sempre similmente alla dichiarazione di una costante cambiando la keyword da const a var. Tuttavia, una variabile non può essere inizializzata all’interno di una procedura o funzione, ma la si può solo dichiarare come tipo. Se la dichiarazione avviene all’interno di una procedura o funzione, la variabile deve essere inizializzata all’interno della procedura o funzione. Un linguaggio iconico deve essere in grado di essere il più flessibile possibile, ciò significa che deve essere in grado anche di poter inizializzare le variabili anche in fase dichiarativa, come per le costanti. 31 2.2.3 Assegnazione L’assegnazione ha la stessa struttura dell’inizializzazione nella fase di dichiarazione. Il costrutto esprime un legame tra la variabile a sinistra dell’uguaglianza e il risultato dell’espressione alla destra dell’uguaglianza. Oltre all’assegnazione normale, esiste un particolare tipo di assegnazione definita ‘aumentata’. Questo tipo di assegnazione utilizza la variabile che la chiama implicitamente all’interno dell’espressione, senza un esplicito inserimento. Un metalinguaggio esprimerebbe tale costrutto come di seguito i +:= 1 questo equivale a i := i + 1 Oltre all’operatore somma è possibile utilizzare un altro tipo di operatore. Nel linguaggio C l’assegnazione aumentata è molto simile i += 1 Oltre a questo genere di assegnazione, sia in C che in un metalinguaggio, esiste un altro tipo di assegnazione aumentata: quella anticipata e posticipata: 32 posticipata i++ anticipata ++i il risultato finale è identico, tuttavia a seconda dei contesti in cui tale costrutto è inserito assume un contesto nettamente differente. Infatti, in un contesto in cui la variabile ‘i’ è usata come variabile di controllo all’interno di un ciclo, il valore di tale variabile è differente a seconda se è posticipata o anticipata. In Delphi, non esiste un costrutto simile. Si fa un uso esplicito dell’assegnazione, richiamando nell’espressione la variabile da assegnare. L’unica alternativa è l’uso di alcune funzioni, quale Inc(i) In generale, in C l’assegnazione usa il semplice simbolo ‘=’, mentre in Delphi si usano i due simboli ‘:=’; Un metalinguaggio di programmazione iconica deve prevedere l’uso dell’assegnazione aumentata ai soli linguaggi che la prevedono. 2.2.4 Condizione Una condizione esprime il concetto di Verità o Falsità di un predicato. Un predicato è un costrutto elementare, o espressione elementare, che può assumere soltanto un valore booleano. Dunque, la condizione è costituita da uno o più 33 predicati elementari. Quando vi sono più predicati, questi vengono relazionati tra loro attraverso operatori logici o di confronto. Gli operatori di confronto esprimono un valore su un confronto tra due elementi, espressioni o predicati. Sono elencati di seguito alcuni esempi: =, uguaglianza <>, diverso <, minore <=, minore uguale >, maggiore >=, maggiore uguale Gli operatori di confronto sono uguali a quelli di sopra, sia in C che in Delphi. L’unica differenza consiste che in C il significato di diverso è fornito con i simboli ‘!=’ e l’uguaglianza con i simboli ‘==’. Gli operatori logici esprimono un predicato più complesso a partire da predicati elementari. Dipendendo dai valori booleani dei singoli predicati e da gli operatori logici, il predicato complessivo assume un particolare valore che si trova in una ipotetica tabella di verità che, in fase di esecuzione. Gli operatori logici si dividono in duali o unari. Si dice duali quando l’operatore crea il risultato tra due predicati. L’unico operatore logico unario è la negazione. Di seguito gli operatori logici: 34 And Or Not Gli operatori logici in C usano simboli diversi &&, and ||, or !, not In Delphi si usano gli stessi operatori del metalinguaggio precedentemente descritto. Fornite le basi, un esempio di una condizione in un metalinguaggio è A and (B or C) >= (D or (C and A)). la quale è del tutto simile al C e al Delphi. Un metalinguaggio iconico dovrebbe essere in grado di rendere quanto più semplice possibile la visualizzazione di una condizione, anche complessa soprattutto quando vi sono più predicati. 35 2.2.5 Sequenze La sequenza è un particolare tipo di costrutto che serve ad indicare un blocco di istruzioni nel flusso del programma. Tipicamente, viene utilizzato in concomitanza con i cicli o con i costrutti decisionale If..Then..Else e Case. In un metalinguaggio, è possibile usare la forma Begin istruzioni/costrutti End La quale risulta coincidente con il linguaggio Delphi. Nel linguaggio C, si usano simboli diversi { Istruzioni/costrutti } Un linguaggio iconico dovrebbe fornire tale costrutto all’utente. 36 2.2.6 Cicli I Cicli sono costrutti molto importanti nei linguaggi di programmazione, attraverso essi si possono eseguire un numero di volte indefinito una serie di operazioni che altrimenti dovrebbero essere esplicitate. Attraverso i cicli, si possono anche creare multiple diramazioni nel ciclo di vita del programma, in quanto all’interno di essi diverse variabili, dette variabili di controllo del ciclo, possono stravolgere l’andamento del flusso operativo a seconda del valore che esse acquisiscono. Inoltre, si fa spesso uso dei cicli quando si voglia modificare più porzioni di una variabile di tipo array mono o multi dimensionale. In generale i linguaggi contengono al loro interno tre tipi di ciclo: For While Repeat 2.2.6.1 Ciclo For Il costrutto For permette di iterare, un numero di volte ben definito, un insieme di istruzioni. Il numero di ripetizioni viene esplicitato in fase di richiamo del costrutto. Un esempio in un metalinguaggio è For variabile = valore_iniziale a valore_finale istruzione/costrutto 37 Variabile è la variabile di controllo che fa si che limita l’esecuzione del ciclo. Il ciclo ha termine nel momento che la variabile assume il valore di valore finale. In C, il For ha un costrutto diverso For (valore_iniziale, condizione_di_test, incremento) istruzione/costrutto Come si evince, in C fornisce una maggiore flessibilità. Il ciclo viene eseguito fin quando viene verificata la condizione di test, e ad ogni ciclo l’incremento, o anche decremento, è una espressione. Esempi di espressioni per il For in C sono ‘i++’ o ‘i*2’. In Delphi, il costrutto è simile al metalinguaggio, la differenza consiste solo nel simbolo di assegnazione, infatti dove nel metalinguaggio è riportato il simbolo ‘=’, in Delphi è ‘:=’. 2.2.6.2 Ciclo While Il costrutto While è molto simile, a livello concettuale, al For. La differenza è che in questo costrutto le istruzioni sono ripetute fin quando la condizione del While è vera. E’ molto importante far si che vi sia almeno un caso in cui la condizione del While assuma un valore false, altrimenti il ciclo sarà infinito e il programma non avrà mai termine. Dunque, bisogna prestare molta attenzione circa le variabili incluse nella condizione del While. In un metalinguaggio il costrutto While assume la seguente forma 38 While ( condizione) do istruzione/costrutto Nel C il costrutto è assume la seguente forma While ( condizione ) istruzione/costrutto In Delphi, il costrutto è identico all’esempio del metalinguaggio. 2.2.6.3 Ciclo Repeat .. Until e Do .. While I costrutti Do .. While e Repeat .. Until sono due costrutti che eseguo un blocco di codice almeno una volta e soltanto dopo aver eseguito il blocco di codice, verificano se la condizione è vera o falsa. In un metalinguaggio questo ciclo assume la seguente struttura Do While ( condizione) Nel linguaggio C il costrutto è quasi simile la differenza consiste nel sostituire ‘BEGIN’ con il simbolo ‘{‘ ed ‘END’ con il simbolo ‘}’ 39 Do While ( condizione) In Delphi vengono utilizzate le parole ‘REPEAT’ e ‘UNTIL’ per sostituire, rispettivamente, ‘DO’ e ‘WHILE’ REPEAT UNTIL ( condizione) 2.2.6.4 Considerazioni sui cicli Non tutti i cicli vengono realizzati dai linguaggi di programmazione. Spesso sono presenti solo i primi due cicli proposti. Tuttavia, è necessario solo una tipologia di ciclo poiché gli altri tipi si possono ottenere da uno solo, anche se, generalmente, i linguaggi di programmazione di basso livello usano i 3 cicli suddetti. Ad esempio, con il ciclo For e il ciclo While possono essere sostituiti dal ciclo While. Un linguaggio di programmazione iconica deve possedere la capacità di poter rappresentare tutti i cicli presentati. Per maggior chiarezza e comprensione è anche utile che abbia una sola icona che rappresenti il concetto di ciclo, ma che fornisca la possibilità di scegliere all’utente quale scegliere, tra i vari cicli. 40 2.2.7 If .. Then .. Else Un altro costrutto molto importante è l’If .. Then .. Else. Con tale struttura si ha la possibilità di discriminare una condizione eseguendo, a seconda del risultato di quest’ultima, un blocco di codice oppure un altro. Tale costrutto può anche essere annidato fornendo una maggiore complessità di diramazioni al ciclo di vita del programma. Un metalinguaggio ha una struttura simile alla seguente If ( condizione) Then istruzione/costrutto Else istruzione/costrutto Se la condizione è vera allora il ciclo di vita del programma continuerà nel primo blocco di codice, saltando il blocco che è subito dopo Else. Se la condizione è falsa allora il programma non terrà conto del primo blocco di codice, ma passerà direttamente al secondo blocco, continuando poi normalmente. Ad esempio If ((a>10) and (a<50)) Then istruzione/costrutto Else 41 istruzione/costrutto ovvero: se ‘a’ è maggiore di 10 ed ‘a’ è minore di 50 allora si prende in considerazione il primo blocco non tenendo conto del secondo. Altrimenti, si procede col secondo blocco, saltando il primo. In Delphi il costrutto coincide con l’esempio del metalinguaggio. In C il costrutto si differenzia in quanto manca l’uso della keyword ‘Then’ e dalla dichiarazione del blocco del codice. Un linguaggio di programmazione visuale deve essere in grado di fornire con chiarezza sia la costruzione della condizione usata nel costrutto sia le sue diramazioni, facendo si che l’utente abbia chiaro il significato delle icone al fine di evitare un uso improprio del costrutto. 2.2.8 Break, Continue e Return I costrutti Break, Continue e Return sono anch’essi molto importanti sul ciclo di vita di un programma. Ognuno di essi è adibito ad una ben specifica funzione. Sono inclusi sia nei metalinguaggi, sia in C che in Delphi, e dovrebbero essere inclusi anche in un linguaggio iconico. Le keyword Break e Continue sono uguali sia nei metalinguaggi, che in C e in Delphi. 42 2.2.8.1 Break Break è un’istruzione che permette di uscire da un ciclo senza uscire dalla funzione o procedura. Può essere associato ad un costrutto If all’interno di un ciclo, e bisogna utilizzarlo con attenzione. 2.2.8.2 Continue Questo costrutto permette ad un ciclo di saltare tutto ciò che vi è nel blocco del codice facendo ricominciare la ripetizione del blocco, ma con l’incremento della variabile di controllo come se si fosse completato il precedente ciclo. 2.2.8.3 Return Return è un costrutto che permette alle funzioni di restituire un valore ben definito in accordo col tipo dichiarato della funzione. Sia in un metalinguaggio che in C, Return è seguito da una espressione. Quando Return viene inserito all’interno di una procedura allora Return può non precedere alcuna espressione o al massimo il valore ‘0’ (zero). Return viene usato come il seguente Return A+B 43 In Delphi, solo di recente si è fornito alla keyword Exit la possibilità di uscire da una funzione fornendo il valore di un’espressione. In Delphi, tipicamente, per restituire il valore di una funzione si procede in due modi: o si richiama la keyword Result e a questa si assegna il valore di un’espressione oppure si richiama il nome della funzione stessa assegnandole un valore di un’espressione. Ad esempio se la funziona si chiama Mia_funzione, in Delphi si usa la seguente sintassi Mia_funzione := 5 oppure Result := 5 oppure Exit(5) E’ utile sottolineare, che in Delphi la keyword Exit permette di uscire dall’esecuzione di una funzione senza fornire un valore, ma tra parentesi tonde, come nell’esempio di sopra, vi è un valore in accordo con il tipo della funzione, allora Exit oltre ad uscire dalla funzione fornisce anche il valore come risultato. Un linguaggio di programmazione visuale necessita di possedere tale costrutto. 2.2.9 Switch .. Case Tale costrutto è fornito da quasi tutti i linguaggi di programmazione. In un metalinguaggio, esso ha la seguente struttura 44 Switch (espressione) { Case elem1: Blocco_di_codice1 break; Case elem2: Blocco_di_codice2 break; … Case elemn: Blocco_di_codicen break; Default: Blocco_di_codice break; } Dalla sua struttura si evince la sua grande utilità. Esso permette di poter scegliere quale blocco di codice verrà preso in considerazione in base al valore che espressione assume. La keyword case indica i possibili valori da tenere in considerazione e che sono specificati dagli elementi. Essi, inoltre, sono dello stesso tipo del valore che assume l’espressione. La parola chiave default è opzionale e fa in modo che il costrutto case scelga il suo blocco di codice nel 45 caso in cui nessuno degli elementi corrispondono al valore dell’espressione. Inoltre, l’istruzione Break è inserita poiché alcuni linguaggi di programmazione, come il C, dopo aver eseguito il blocco di codice identificato dall’elemento, continuano a verificare se il valore di espressione è verificato per altri casi. Questo in quanto è possibile modificare il valore assegnato all’espressione se questa è una variabile. Questo costrutto può essere pensato come una serie di costrutti If i quali sono o annidati tra di loro o messi in successione. L’utilità di questo costrutto è rimarchevole e quasi tutti i programmi, semplici o complessi, lo usano almeno una volta. Nel linguaggio C, tale costrutto trova la stessa forma come nel caso del metalinguaggio sopra specificato. In Pascal, il costrutto assume una forma diversa, ma cognitivamente simile Case (espressione) Begin elem1: Blocco_di_codice1 elem2: Blocco_di_codice2 … elemn: Blocco_di_codicen Else Blocco_di_codice 46 End Si nota che la parola Switch viene sostituita da Case e Case non figura prima dei valori del dominio dell’espressione. Inoltre, la parola Deafault viene sostituita da Else e non viene seguito dal simbolo ‘:’. Da notare che in Pascal, il costrutto Case non fa uso della parola Break, questo in quanto il costrutto stesso quando identifica il valore dell’elemento esegue solo il blocco di codice legato al valore dell’espressione. Un linguaggio di programmazione iconica deve prevedere l’uso di tale costrutto e deve anche provvedere ad una chiara e distinta identificazione di ogni valore che l’espressione può assumere, fornendo quindi all’utente un modo immediato per comprendere le possibili scelte. 2.2.10 Procedure e Funzioni Particolari costrutti sono le Procedure e le Funzioni. Una Procedura o Funzione è un blocco di codice isolato. Tale blocco di codice deve essere identificato con un nome per poter essere richiamato dal resto del programma. Questo approccio permette di strutturare meglio la complessità di un programma delegando a parti di codice un suo funzionamento. Inoltre, esse permettono di diminuire la ridondanza di codice all’interno del programma, in quanto spesso, durante il ciclo di vita di un applicativo, occorre che si eseguano più volte porzioni di codice o quando si vuole ottenere un risultato di un qualche tipi 47 attraverso le funzioni, o si vuole ottenere un cambiamento nel programma attraverso le procedure. La differenza essenziale tra una procedura ed una funzione è che una funzione ritorna un valore o, in modo equivalente, la funzione assume il valore del risultato del blocco di codice che rappresenta, mentre una procedura non restituisce alcun risultato. 2.2.10.1 Procedura Un metalinguaggio utilizza la seguente struttura Procedure Mia_Procedura(Param1, Param1, … , Paramn) Begin … End La parola Procedura indica che si sta dichiarando una procedura ed il nome che ne segue Mia_Procedura è il nome che si utilizzerà per richiamarla. I Parametri tra le parentesi tonde significa che la procedura, per essere chiamata, necessita di una serie di parametri in ingresso. Questi parametri possono essere passati per valore, o per referenza che significa passare ‘fisicamente’ una istanza di un tipo alla procedura stessa in modo che essa lo possa manipolare. E’ possibile anche inizializzare uno o più parametri qualora si preveda un valore di default di alcuni parametri. Infine il blocco di codice tra Begin ed End 48 costituisce tutto il codice a cui ci si riferisce quando si chiama la Mia_Procedura. In C il costrutto della Procedura è come segue Void Mia_Procedura(Param1, Param1, … , Paramn) { … } In C, quindi, non vi è una esplicita dichiarazione della Procedura, in quanto in realtà non esiste la diversificazione netta tra procedura e funzione. Questa viene compresa dal fatto che il tipo Void è un tipo nullo che se fornito ad una funzione la si dichiara automaticamente come procedura. Per concludere, in C una procedura non necessita del return, in quanto non ritorna alcun valore, sebbene l’inserimento di tale keyword è permesso. In Pascal, il costrutto della Procedura è del tutto simile all’esempio del metalinguaggio riportato. E’ da notare che tra la dichiarazione della procedura e la parola Begin è possibile definire diverse costanti, variabili, tipi, etichette, ecc. Queste non sono i parametri richiesti dal programma ma sono istanze di costrutti i quali possono essere utilizzati soltanto all’interno della Procedura che li dichiara, e quindi non in qualunque altra porzione dell’applicativo. Questa particolarità viene chiamata Visibilità Locale, in quanto tali costrutti sono ‘visti’ solo dalla procedura che li istanzia. Esiste anche una Visibilità Globale, in qualunque linguaggio di programmazione che significa che le istanze dichiarate 49 sono accessibili da qualunque porzione dell’applicativo, anche da qualunque funzione o procedura. Un linguaggio di programmazione iconica necessita di rappresentare tale costrutto, in quanto essenziale alla diversificazione del flusso logico del programma che si sviluppa. Dunque, oltre a fornire una rappresentazione iconica, tale linguaggio, deve essere in grado di mostrare visivamente anche il suo contenuto, con i dovuti accorgimenti. 2.2.10.2 Funzione Il costrutto Funzione è molto simile a quello della Procedura, unica differenza è che in fase dichiarativa deve essere assegnato un tipo di dato che la Funzione deve restituire. Di seguito la forma del costrutto in un metalinguaggio Tipo Mia_Funzione(Param1, Param1, … , Paramn) Begin … Return( Risultato) End Il tipo di dato può essere un qualunque tipo di dato che può assumere qualunque variabile o costante. I parametri seguono lo stesso criterio della Procedura, così come il Blocco di Codice. La parola Return è fondamentale per 50 fornire, alla porzione del codice che richiama la Funzione, il Risultato dei calcoli della funzione. Un esempio tipico di una funzione è Int Somma( Int a, Int b) Begin Return (a + b); End; Dove Int è il tipo di dato Intero e definisce che il risultato, o il valore assunto dalla funzione alla fine del suo ciclo di vita, è di tipo Intero. Somma è il nome della funzione, è può essere richiamata dal porgramma con la seguente sintassi Somma(a, b) Dove ‘a’ e ‘b’ sono due variabili o costanti che hanno un qualsiasi valore nell’insieme dei numeri interi. In C il costrutto è simile Int Somma( Int a, Int b) { Return (a + b); } 51 In Pascal, il costrutto è molto simile, tuttavia la dichiarazione del tipo della funzione è fornita alla fine della dichiarazione del nome e dei suoi parametri. Di seguito un esempio Function Somma( Integer a; Integer b): Integer; Begin Result := a + b; End; Un linguaggio iconico di programmazione deve prevedere l’uso di tale costrutto e deve essere in grado di fornire una sua rappresentazione iconica. Inoltre, sia per la Funzione che per la Procedura, tale linguaggio deve eseguire un controllo preventivo sui tipi di dati in ingresso, al fine di guidare l’utente nel costruire un codice sicuro e, quindi, evitare errori in fase di compilazione. 2.3 Tipi di dato Nei linguaggi di programmazione esistono vari tipi di dati primitivi forniti. Un tipo di dato altro non è che una caratteristica che fornisce il significato e il comportamento di una variabile, costante o funzione. I tipi si distinguono in primitivi e di enumerazione. 52 2.3.1 Tipi primitivi I tipi primitivi, essenzialmente, sono i seguenti Void Char Int Short Long Float Double A questi si uniscono le seguenti due definizioni di range per i numeri Signed Unsigned In particolare, nella definizione dei tipi numerici, qualora non venga specificato il range, il tipo di dato viene considerato in automatico ‘Signed’. Void serve essenzialmente per dichiarare una funzione come una procedura. Tuttavia, in alcuni contesti, viene usato come tipo per i puntatori, per il quale si richiede un uso intensivo di tecniche di ‘Type Casting’ forniti dai vari linguaggi. 53 Il tipo Char viene considerato come un byte ma anche come un singolo carattere, in quanto nel codice Ascii esteso i caratteri possibili rientrano nel range che spazia tra 0 e 255. Nella tabella 2.1 viene presentata una rassegna dei tipi primitivi numerici nel linguaggio C TIPO Dimensione Signed Char 1 Byte Unsigned Char 1 Signed Short 2 Unsigned Short 2 Signed Int 4 Unsigned Int 4 Signed Long 8 Unsigned Long 8 Float 4 Long Double 8 Tabella 2.1 Tipi numerici in C in 2.3.2 Tipi di enumerazioni I tipi enumerativi sono dei tipi appartenenti ad un insieme ben definito, generalmente fornito dallo sviluppatore. Il costrutto prende forma come nella seguente Enum Nome_Insieme(Elem1, Elem2, … , Elemn) 54 Enum dichiara che si sta creando un insieme di dati, che contiene elementi ben specificati. Nome Insieme identificherà l’insieme. Gli elementi costituiscono i valori che l’insieme contiene. Questi vengono interpretati dal compilatore come dei valori numerici, sebbene agli elementi possiamo dare un interpretazione diversa. Ad esempio Enum Colori (Blu, Verde, Rosso) Significa che si sta creando un insieme chiamato Colori e gli elementi di questo insieme sono: Blu, Verde e Rosso, che assumono in default i valori, rispettivamente, 0, 1 e 2. E’ possibile specificare i valori che gli elementi assumono, fornendo un valore iniziale agli elementi, ad esempio Enum Colori (Blu= 1, Verde, Rosso) Indica che Blu assume il valore 0, e gli altri elementi seguiranno da questo, quindi, Verde sarà uguale ad 1 e Rosso a 2. Le enum ci vengono incontro quando abbiamo a che fare, quindi, con una lista di valori. Questo significa poter astrarre i valori numerici a interpretazioni soggettive. Un utile esempio è il seguente 55 Case (espressione) { Case Blu: Blocco_di_codice1 Case Verde: Blocco_di_codice2 … Case Giallo: Blocco_di_codicen } il codice sopra fa si che quando espressione assume il valore di un elemento del tipo Colori allora eseguirà il rispettivo blocco di codice indicato. Cambiare l’ordine del costrutto Case o gli elementi dell’insieme Colori non varia il comportamento logico del programma. In Pascal, le enumerazioni assumono la stessa forma ma vengono esplicitamente dichiarate come tipi. Un linguaggio di programmazione visuale deve assicurare l’esistenza delle enumerazioni potendo, così, fornire un potente strumento di programmazione per la gestione degli insiemi. 56 2.3.3 Array Sia i tipi primitivi che le strutture sono dei tipi di dati generici. Precedentemente si è accennato all’esistenza di un particolare tipo di struttura, gli Array. Un array può essere definito come una “collezione organizzata di oggetti”. Il concetto di “collezione” implica che tali oggetti siano dello stesso tipo, così, prendendo spunto dal mondo reale, potremmo definire un array di Persone, che, quindi non può contenere nessun “oggetto animale”; un array in C è una collezione di variabili dello stesso tipo. “Organizzata” implica che sia possibile identificare univocamente tutti gli oggeti dell’array in modo sistematico; questo in C viene fatto tramite l’uso di indici numerici che, in un array di dimensione N, vanno da 0 ad N-1. In C, un array viene dichiarato nella seguente forma Tipo Mio_array[N] dove Tipo specifica il tipo di dato che tutti gli elementi dell’array avranno, Mio_Array è il nome della variabile o costante, ed N identifica il numero di elementi che l’array conterrà. In Pascal, un array viene dichiarato come segue Mio_Array: Array[N] of Tipo E’ fondamentale che un linguaggio di programmazione visuale abbia tale tipo di struttura, in quanto essenziale in ogni linguaggio di programmazione 57 2.3.4 Strutture Un altro importante oggetto, che viene considerato l’antenato di molte altre strutture, come le Classi, è la Struttura. Una struttura o Record è un tipo di dato capace di incapsulare più elementi distinti all’interno di esso. Concettualmente, è un dato eterogeneo costituito da più variabili e strutture diverse. Le strutture sostanzialmente permettono l’aggregazione di più variabili, in modo simile a quella degli array, ma a differenza di questi non ordinata e non omogenea (una struttura può contenere variabili di tipo diverso). Per denotare una struttura si usa la parola chiave struct seguita dal nome identificativo della struttura, che è opzionale. In C, si usa la seguente forma per definire una struttura Struct Persona { char Nome[100]; char Cognome[50]; int Altezza; } Il codice di sopra indica che si è creato una struttura chiamata Persona che ha tre variabili: Nome, un array di 100 caratteri; Cognome un array di 50 caratteri; Altezza, una variabile di tipo intero. Per poter istanziare una variabile di tipo struttura di tipo Persona si usa la seguente sintassi Struct Persona Guido 58 Le strutture servono per poter dare una migliore lettura del codice e una migliore usabilità del codice, fornendo allo sviluppatore uno strumento che gli permetterà di comprendere a livello logico e concettuale l’uso delle variabili. 2.4 Analisi finale Si è discusso dei principali Costrutti, dei tipi, degli array e delle strutture di dati che ogni linguaggio di programmazione, di basso o alto livello, dovrebbe avere, fornendo chiari esempi per comprendere la maggior parte delle caratteristiche che ognuno di questi elementi possiede. Nel capitolo successivo si analizzerà lo sviluppo di un framework di programmazione iconica. 59 Capitolo III SVILUPPO DI UN LINGUAGGIO DI PROGRAMMAZIONE ICONICA 3.1 Sviluppo del Framework Lo sviluppo di un framework deve seguire criteri ben precisi, dalla facilità di comprensione del framework alla facilità di utilizzo dello stesso. Ci si è chiesto quale potesse essere un modello visuale da utilizzare per facilitare sia la comprensione logica della stesura di un generico programma sia la facilità nel sviluppare applicativi. Tra i vari modelli possibili si è scelto di utilizzare un modello che più si avvicina a quello dei diagrammi a blocchi, per varie ragioni: E’ un chiaro modello di implementazione concettuale circa il comportamento di un algoritmo E’ un modello utilizzato da tutte le aziende per rappresentare i processi logici dei vari algoritmi E’ un modello facilmente modificabile qualora si volessero apportare miglioramenti al codice iconico. 60 E’ un tipo di schema nel quale le icone forniscono un immediato feedback intuitivo, atto a identificare i processi dell’algoritmo. Ogni icona del diagramma a blocchi rappresenta un tipo particolare di dato, un’istruzione oppure una funzione. Ogni icona è già standardizzata in base a ciò che deve rappresentare, quindi risulta essere estremamente intuitivo l’uso del framework. Inoltre, l’uso del diagramma a blocchi garantisce l’aspetto cognitivo del flusso dei dati, proprio come viene sviluppato un codice all’interno di un qualunque IDE. Questo fornisce sia un’attenta leggibilità del codice sia una corretta percezione comportamento logico dell’algoritmo che si sviluppa. Una rappresentazione iconica di questo genere favorisce un tipo di programmazione attiva: i dati vengono manipolati direttamente, e si ha la sensazione di implementare il codice anche se questo non è realmente così. Un linguaggio di programmazione iconica, come quelli classici, necessita anche di un parser. Nel seguito si descriverà tale oggetto. Inoltre, tale rappresentazione formula un meta linguaggio visuale, facilmente esportabile in qualunque altro linguaggio di programmazione classico. Così facendo, è possibile implementare qualunque linguaggio di programmazione oltre al C: C++, Pascal, Delphi, Php, Java, Javascript, Ruby, ecc. In quanto, il framework stesso costruisce anche il codice testuale dell’algoritmo che si sta costruendo. 61 3.2 Sviluppo del linguaggio iconico dal punto di vista concettuale Nel seguito verranno fornite le logiche di implementazione per lo sviluppo di un linguaggio iconico. I concetti fondamentali sono Il flusso logico delle istruzioni per il linguaggio; La configurazione iconica rappresentante i principali costrutti; La rappresentazione visiva, in tempo reale, del codice di programmazione sviluppato durante la stesura del codice iconico; 3.2.1 Implementazione concettuale del flusso Per fornire un flusso logico all’implementazione mediante un linguaggio di programmazione visuale, si è reso necessario studiare su come gli IDE forniscono questa caratteristica. Generalmente, durante la stesura di un codice, gli ambienti di sviluppo seguono le definizioni e le istruzioni dall’alto verso il basso, partendo dall’inizio delle funzioni o procedure giungendo alla fine delle stesse. Seguendo questa linea di principio, si è optato per lo stesso approccio fornendo un punto di riferimento per ogni funzione e procedura. Il punto di riferimento consiste in una icona Start che costituisce il punto di inizio. Da questa si “agganceranno” le icone seguendo un flusso che costituisce il codice della funzione o procedura. Le icone verranno collegate mediante degl’archi che costituiscono gli oggetti di collegamento del flusso. Questo garantisce la 62 continuità tra un costrutto ed un altro. Inoltre, questo permette la realizzazione di controlli sulle variabili, costanti, funzioni e procedure, nel seguente modo: ogni costrutto (variabile, costante, funzione e procedura) non può avere lo stesso nome di un altro costrutto se questo è utilizzato da un altro. L’ambiente di sviluppo iconico, così, risale lungo gli archi per verificare quali nomi sono stati assegnati ad altri costrutti, impedendo ed evitando la ridefinizione di essi. I costrutti (funzioni, procedure, case, if e le espressioni) hanno visibilità di quali altri costrutti possono utilizzare, guidando l’utente ad utilizzare i giusti costrutti e fornendo una programmazione robusta del codice senza possibilità di errore. Ogni qual volta si deve inizializzare o modificare un costrutto, questo esegue un controllo preventivo su quali altri costrutti può utilizzare fornendo allo sviluppatore un aiuto nello scegliere i giusti oggetti. La visualizzazione diagrammatica del codice fornisce un buon metodo per comprendere il comportamento delle funzioni. Il collegamento delle icone mediante archi migliora la visibilità concettuale garantendo il flusso e su come questo influisce nell’algoritmo. Così, ogni oggetto assolve un determinato compito nell’algoritmo e fornisce una chiara visione del tutto. Esempio di collegamento 63 Fig. 3.1 Esempio di collegamento tra Start ed una variabile Inoltre, gli archi assumeranno un colore diverso a seconda del livello di annidamento al quale si riferiscono. Sono stati definiti 10 colori per gli archi, uno per ogni livello. I colori sono Bianco Rosso Verde Blu Argento Fucsia Giallo Verde acceso Verde acqua Porpora 64 3.2.2 Rappresentazione visiva dei costrutti principali Nel seguito verranno fornite le modalità di visualizzazione dei costrutti. Ogni costrutto ha una sua icona ben definita. Le caratteristiche che contraddistinguono le icone sono Colore del contorno Colore del riempimento dell’icona Forma dell’icona Testo contenuto nell’icona Creazione di una immagine custom per le funzioni Nel seguito, per ogni caratteristica si fornirà la rappresentazione dei costrutti. 3.2.2.1 Colore del contorno Il contorno delle icone è, generalmente diverso da costrutto a costrutto. Esso è importante, per fornire un primo impatto cognitivo circa la rappresentazione dell’oggetto e la memorizzazione del costrutto. L’icona dello Start ha un contorno di colore rosso. Questo poiché, essendo un oggetto fondamentale per il flusso, è importante che risalti tra gli altri oggetti e si diversifichi istantaneamente. 65 Le variabili, e le costanti, hanno eguale contorno. Il contorno differisce a seconda se il tipo è numerico discreto, numerico in virgola mobile o di tipo stringa. Il numerico discreto usa un colore blu, mentre quello in virgola mobile usa un colore di tipo arancione. Infine, il tipo stringa usa un colore fucsia. Questo permette di distinguere immediatamente il tipo di dato che contraddistingue la variabile o la costante. I cicli sono contraddistinti da un contorno verde mare. Tra essi stessi, come si vedrà in seguito, saranno contraddistinti dal testo contenuto nell’icona.. Il costrutto delle condizioni, l’If, usa il giallo per il suo contorno. L’icona costituente il blocco di codice ha un contorno nero. I costrutti break, continue ed exit usano lo stesso colore per il contorno, il colore olivastro. Essi si distingueranno, come per i cicli, dal testo contenuto nell’icona. Il case userà un colore porpora per il contorno, mentre i vari casi, che da esso ne deriveranno, useranno un colore diverso a seconda del numero di case. Il costrutto return è contraddistinto dal colore verde. Gli oggetti begin ed end, usano un colore che cambia a seconda del livello di annidamento nei quali sono inseriti, ovvero il colore sarà coincidente al colore del flusso, questo per fornire una migliore comprensione a quale annidamento appartengono e si riferiscono. L’assegnazione usa un contorno verde, ma sarà differenziata dal return per mezzo della sua forma. Le funzioni o procedure, avranno eguale forma come espresso più avanti, ma il colore del contorno sarà diverso: per le funzioni si userà un colore viola, mentre per le procedure un colore blu. 66 Inoltre, l’utente ha la facoltà di scegliere il colore del contorno per le funzioni, definite da lui, di cui desidera impostare una icona personale. Oltre al colore del contorno, si sottolinea che al fine di identificare l’icona selezionata il suo contorno diventa maggiormente spesso, per poi tornare normale quando viene deselezionata. 3.2.2.2 Colore del riempimento Generalmente il colore di riempimento delle icone sarà uguale per tutte al bianco. Vi sono dei casi particolari elencati di seguito L’icona diventa verde tenue quando il mouse vi passa di sopra, per poi tornare normale quando questo esce dal suo riquadro; L’icona assume un colore di riempimento azzurro tenue quando questa viene selezionata. Il suo colore tornerà nuovamente bianco quando l’oggetto verrà deselezionato. L’icona assume un colore grigio quando questa non è inizializzata o non contiene alcun codice. 3.2.2.3 Forme delle icone Ogni icona userà una forma differente. I costrutti che avranno uguale forma saranno differenziati dai colori dei contorni e dal testo che avranno all’interno. 67 Lo Start ha una forma rettangolare allungata in larghezza ed i suoi bordi sono smussati. Questo, visivamente, oltre al suo contorno rosso cattura immediatamente l’attenzione fornendo un chiaro punto di riferimento per l’inizio del flusso. Le variabili e le costanti hanno anch’esse una forma rettangolare, allungata in larghezza. Tuttavia, a differenza dello Start gli angoli sono spigolosi. Questa forma coincide con la funzione intrinseca delle variabili e le costanti. Un discorso diverso riguarda i cicli. Essi, concettualmente, forniscono un punto di interruzione al flusso dei dati, in quanto il flusso continuerà a proseguire solo dopo che verrà ripetuto più volte il blocco di codice a cui essi fanno riferimento. Inoltre, proprio perché i cicli si riferiscono a porzioni di codice di lunghezza variabile, da poche righe di codice a enormi porzioni, si è scelto di utilizzare una forma di un quadrato smussato. Inoltre, l’icona è più grande rispetto alle altre per evidenziare che dalle sue diramazioni vi è un ulteriore codice, quello iterato, di lunghezza variabile. Per rendere più vicino il linguaggio iconico del framework al linguaggio dei diagrammi a blocchi, si è deciso di utilizzare per il costrutto If una forma romboidale, in quanto esso ha la desiderabile proprietà visiva di fornire un immediato senso delle possibili diramazioni del concetto di verità o falsità risultante dall’espressione che verifica. L’icona del blocco di codice usa una forma quadrangolare, simile a quella dei cicli. Tuttavia, a differenza di essi, i suoi angoli sono spigolosi. Questo fornisce un senso di incapsulamento del codice, che è esattamente il concetto che si vuole rendere. 68 I costrutti Break, Continue ed Exit sono rappresentati da un cerchio. Ciò che li differenzia è lo stile del contorno. Generalmente, il cerchio, nell’immaginario collettivo, assume un concetto di continuità di un ciclo, esattamente il concetto che fornisce il Continue. Il Break fornisce un concetto di interruzione senza, tuttavia, uscire dalla funzione o procedura, per questo motivo si usa un contorno tratteggiato-punto. Infine, l’Exit, esprimendo un significato di uscita da una funzione e quindi un’interruzione di tipo forte, si è scelto di usare un contorno tratteggiato. Il costrutto Switch esprime un concetto di multi-opzionalità di un’espressione, le cui alternative spostano il flusso del programma verso una relativa porzione di codice. Queste considerazioni hanno influenzato l’ideazione della forma dell’icona portando all’uso di un rettangolo allungato in altezza, che assume, figurativamente ed in maniera pertinente, la rappresentazione mentale espressa dal struttura sintattica. Il Return è quasi concettualmente l’opposto dello Start, in quanto è il punto finale di ogni funzione. Inoltre, il Return fornisce, in uscita della funzione, un valore. Per tali considerazioni si è deciso di assumere la stessa forma dello Start con la differenza nel testo e nel colore del contorno. Il Begin e l’End usano la stessa forma dello Start, ma ne cambiano il testo e il contorno. L’Assegnazione usa un triangolo equilatero, con un vertice rivolto verso destra, così da esprimere il concetto di ‘inserimento’ all’interno di una variabile. Le funzioni o procedure usano una forma rettangolare, con angoli spigolosi, poco più alta delle variabili, questo associa il loro richiamo anche al significato 69 di un blocco di codice richiesto da altre parti del programma. La differenza tra le funzioni e le procedure consiste nel contorno e nel testo Le funzioni personalizzate potranno assumere la forma desiderata dall’utente o la stessa forma delle funzioni o procedure. La dimensione massima in altezza e larghezza è limitata a 65 x 65 pixel. Nel caso in cui l’immagine superi tali vincoli, questa verrà ridimensionata ai limiti. L’immagine, inoltre, deve essere nei seguenti formati: Bitmap, Jpeg o Icon. 3.2.2.4 Testo delle icone Il testo delle icone è rappresentativo del costrutto che indicano. Quasi tutte le icone usano il proprio tipo di costrutto come testo, eccetto alcuni casi. Le icone delle variabili e delle costanti indicano se il dato è una variabile o una costante seguito dal nome del dato. L’Etichetta assume il valore che le si fornisce. I casi dello Switch..Case usano il testo delle varie opzioni in accordo al tipo di espressione usato nello Switch, così da offrire un immediato riscontro. L’Assegnazione usa come testo soltanto il nome della variabile al quale si assegna il risultato di un’espressione, in tale maniera risalterà istantaneamente su quale variabile si eseguirà l’operazione Le icone delle funzioni e procedure, quelle non personalizzate dall’utente, useranno il loro stesso nome, così da rendere agevole l’identificazione di esse. 70 3.3 Esplicitazione del codice sorgente mediante l’uso delle icone Come detto, durante la stesura del codice iconico, l’applicativo fornisce il codice sorgente che si sta implementando. Questo è visionabile in tempo reale, alla destra del codice iconico. Per eseguire questo si inserisce un oggetto che identifica un vero e proprio Text Editor, con l’unica differenza che viene disabilitata la facoltà di modificare il codice sorgente direttamente da questo oggetto. La codifica inserita in questa classe sfrutta il linguaggio XHTML, in quanto appropriato per nascondere vari elementi tag non necessari a chi usa il programma ma utili all’associazione tra gli elementi iconici e il sorgente visualizzato. Questo approccio, inoltre, fa si che sia possibile esportare il codice in versione HTML, oltre che classico, identificando i vari costrutti e le varie keyword. Ogni oggetto iconico fornisce un particolare codice associato ad esso. Così, le variabili e le costanti godono di un’inizializzazione e forniscono il codice per inizializzarle. Se, ad esempio, si inserisce un’icona di una costante, questa crea un codice di tipo “const int costante = 3”. L’icona di un ciclo For fornisce un codice simile al “for(k = 1, k<10, k++)”. E così a seguire. 71 seguente 3.4 Integratore iconico con un Parser XML In informatica, il parsing o analisi sintattica è il processo atto ad analizzare uno stream continuo in input (letto per esempio da un file o una tastiera) in modo da determinare la sua struttura grammaticale grazie ad una data grammatica formale. Un parser è un programma che esegue questo compito. Tipicamente, il termine italiano viene utilizzato per riferirsi al riconoscimento di una grammatica e alla conseguente costruzione di un albero sintattico, che mostra le regole utilizzate durante il riconoscimento dall'input; l'albero sintattico viene poi visitato (anche più volte) durante l'esecuzione di un interprete o di un compilatore. Nella maggior parte dei linguaggi, tuttavia, l'analisi sintattica opera su una sequenza di token in cui l'analizzatore lessicale spezzetta l'input. Pertanto, il termine parser spesso viene usato per indicare l'insieme della analisi lessicale e della analisi sintattica vera e propria. I sorgenti di un linguaggio iconico devono essere salvati e caricati come negl’altri linguaggi di programmazione. Ciò significa che si devono creare dei file per questi linguaggi. Per realizzare tali sorgenti è necessario diversificare e quindi realizzare un parser che diversifichi ogni oggetto dagl’altri, secondo le caratteristiche di questi. Si è scelto di utilizzare, quale parser, una classe di oggetti, opportunamente modificata, che sfrutta la semplicità e la potenza del linguaggio XML. Inoltre, tale approccio fornisce una forte robustezza ai dati, evitando di generare errori di analisi del parser 72 3.5 Indicizzatore di librerie generiche Per fornire un uso anche dei linguaggi non iconici, sono state implementate delle classi e delle interfacce che incapsulano le funzioni di una libreria di Perl, anche detto Practical Extraction and Report Language. Sebbene, tali classi ed interfacce possano essere utili ad implementare un parser completo, è stato necessario, per l’implementazione dell’applicativo, fornire loro solo la capacità di poter recuperare i prototipi da un testo in linguaggio C. Tali classi sono riutilizzabili anche per implementazioni future e per integrare ulteriori linguaggi. Per implementare tale indicizzatore si sono incapsulate, all’interno di tale classi e interfacce, le regular expression. 3.5.1 Regular Expression Le Regular expressions, o espressioni regolari anche dette regex sono dei linguaggi per descrivere la “forma” o la “sintassi” di una stringa (una stringa è un testo qualunque, di qualunque lunghezza, una sequenza di caratteri). Con esso si possono effettuare ricerche, e quindi sostituzioni, molto complesse! Verificare che un testo sia conforme ad alcune caratteristiche e segue una certa sintassi, ad esempio verificare se un testo è un indirizzo email o un url valido. Talvolta le regex hanno piccole differenze tra un programma e l’altro o tra un linguaggio di programmazione ed un altro ma il loro concetto ed utilizzo resta lo stesso. 73 Le espressioni regolari sono composte da costanti e operatori che denotano insiemi di stringhe, e da operazioni tra questi insiemi. Dato un alfabeto finito, sono definite le seguenti costanti: 1. 2. o , insieme vuoto , stringa vuota, ovvero la stringa di lunghezza 0 3. , carattere, e le seguenti operazioni: 1. concatenazione: RS o 2. unione: indica l'insieme indica l'unione dei due insiemi 3. stella di Kleene: indica l'insieme che contiene tutte le possibili iterazioni ottenibili dagli elementi di R 4. intersezione: indica l'intersezione tra i due insiemi di stringhe 5. complemento: il complementare di R indica l'insieme delle stringhe appartenenti a Ad esempio dati e , e Allora, possiamo dire che un'espressione regolare, definita a partire da un alfabeto ed stringa un insieme di simboli , è una che rende vera alcuna delle seguenti condizioni: 74 1. 2. 3. o o , dove S e T sono espressioni regolari sull'alfabeto Le espressioni regolari sono utilizzate principalmente da editor di testo per la ricerca e la sostituzione di porzioni del testo. Grande importanza rivestono inoltre nell'informatica teorica, nella quale, ad esempio, sono utilizzate per rappresentare tutti i possibili cammini su un grafo. Tuttavia, le espressioni regolari sono adatte a rappresentare un ristrettissimo insieme di linguaggi formali (se volessimo rappresentare espressioni aritmetiche o linguaggi di programmazione, avremmo già bisogno di utilizzare linguaggi di tipo 2): l'utilizzo dei linguaggi regolari è comunque conveniente, in quanto la chiusura degli stessi alle operazioni di unione, intersezione e complementazione, permettono la costruzione di un'algebra di Boole ed una buona capacità decisionale. La maggior parte dei programmi che utilizzano le RegExp usano tali regole di base fornendo al contempo supporto per le nuove regole estese. In questa sintassi, la maggior parte dei caratteri sono visti come letterali, e trovano solo se stessi. Ad esempio: "a" trova "a"; "bc)" trova "bc)"; ecc. Le eccezioni a questa regola sono i metacaratteri: 75 . Trova un singolo carattere se è nella modalità linea singola, altrimenti se è in multiriga prende tutti i caratteri diversi da \n, ovvero un ritorno a capo. [] Il carattere '-' è letterale solo se è primo o ultimo carattere nelle parentesi: Trova un singolo carattere contenuto nelle parentesi. [abc-] o [-abc]. Per trovare un carattere '[' o ']', il modo più semplice è metterli primi all'interno delle parentesi: [][ab] trova ']', '[', 'a' o 'b'. [^ ] Trova ogni singolo carattere non incluso nelle parentesi. ^ Corrisponde all'inizio della stringa o di ogni riga della stringa, quando usato in modalità multi linea. $ Corrisponde alla fine della stringa o alla posizione immediatamente precedente un carattere di nuova linea, o alla fine di ogni riga della stringa, quando usato in modalità multi linea. () Definisce una "sottoespressione marcata". Il risultato di ciò che è incluso nell'espressione, può essere richiamato in seguito. \n Dove n è una cifra da 1 a 9; trova ciò che la nesima sottoespressione ha trovato. Tale costrutto, detto backreference, estende le potenzialità delle RegExp oltre i linguaggi regolari e non è stato adottato nella sintassi estesa delle RegExp. Sono state definite varie categorie di caratteri, come mostrato nella seguente tabella, che identificano un insieme generico di caratteri. 76 Sintassi normale Significato [A-Z] lettere maiuscole [a-z] lettere minuscole [A-Za-z] lettera sia maiuscole che minuscole [A-Za-z0-9] numeri e lettere maiuscole e minuscole [0-9] numeri [0-9A-Fa-f] numeri in formato esadecimale [.,!?:...] segni di interpunzione [ \t] spazio o TAB Tabella 3.1 Tabella di alcune categorie di caratteri che identificano insiemi di stringhe Inoltre, esistono i quantificatori e gli alias. Entrambi forniscono un utile supporto al riconoscimento delle stringhe. I quantificatori servono ad indicare la quantità di volte che deve essere ripetuto un insieme di stringhe: Quantificatore ? * + {n} {n,m} Significato zero o 1 zero o più uno o più esattamente n volte da n a m volte RegExp abc? abc* abc+ abc{2} abc{2,3} Tabella 3.2 Elenco dei quantificatori e loro significati 77 Gli alias sono scorciatoie dedicate alle categorie di caratteri più usati,e quindi li sostituiscono: ALIAS SIGNIFICATO COORRISPONDE A \d digit (numero) [0-9] \w word (parola) [a-zA-Z0-9_] Include il carattere underscore \s spazio, tab o newline \D qualsiasi non numerico ^\d \W quasiasi non alfanumerico ^\w \S quasiasi ma non lo spazio ^\s [ \t\r\n] Tabella 3.3 Alias e loro corrispettivi 3.6 Analisi finale Si sono analizzate le principali caratteristiche del framework e dell’applicativo, fornendone una chiara visione degli aspetti concettuali. Si è discusso anche delle caratteristiche di integrazione con dei parser per il salvataggio e il recupero dei dati, nonché per il reperimento di funzioni di librerie scritte in linguaggio C. Nel successivo capitolo si discuterà dell’implementazione delle icone e delle rispettive classi, nonché del Text Editor e dell’integratore del parser XML e 78 delle classi che recuperano i prototipi delle librerie e delle procedure e funzioni più importanti dell’applicativo. 79 Capitolo IV IMPLEMENTAZIONE DEL LINGUAGGIO ICONICO DI PROGRAMMAZIONE 4.1 Sviluppo del Linguaggio Per la realizzazione del framework, è stato utilizzato, quale linguaggio di programmazione, il Delphi, versione XE. Delphi è sia un linguaggio di programmazione che un ambiente di sviluppo. Come linguaggio, è un’estensione del Pascal verso la programmazione orientata agli oggetti (Object Oriented Programming). Si è fatto un uso intensivo dei paradigmi di ereditarietà e polimorfismo delle classi e degli oggetti, oltre ad alcune tecniche avanzate di programmazione disponibili sul sistema di sviluppo. 80 4.1.1 Cenni sull’ereditarietà e sul polimorfismo I vari linguaggi di programmazione di alto livello forniscono classi ed oggetti. Come strumenti di sviluppo. Gli oggetti, anche detti componenti o controlli, sono delle classi specializzate nella visualizzazione di varie forme, le quali forniscono all’utente un’interfaccia di comunicazione Uomo-Macchina per interagire con l’applicativo. Esempi di componenti sono i bottoni, le etichette, le varie forme checkbox, ecc. Esempi di controlli sono le immagini, le progress bar, ecc. Questi sono caratterizzati da proprietà quali ereditarietà e polimorfismo. L’ereditarietà consiste nel creare una classe B partendo da un’altra classe A. Se la classe A possiede un insieme di proprietà e funzioni, la classe B eredità le stesse caratteristiche. Questa è una tecnica tanto utile quanto potente, in quanto permette una veloce stesura del codice concentrandosi su alcuni aspetti chiave quali le proprietà, le funzioni e i comportamenti che tutte le classi avranno se diventassero figlie di una classe rispetto ad altre. Il polimorfismo è una conseguenza dell’aggiunzione di una o più proprietà, funzioni o caratteristiche ad una classe che ne ha ereditate altre da una classe genitrice. Verrà qui di seguito si fornisce un esempio classico per spiegare l’ereditarietà e il polimorfismo. Si può creare una classe chiamata “Animale” ed assegnare ad essa delle proprietà quali “Zampe” e “Coda”. E’ possibile creare due altre classi “Cane” e “Gatto” che sono derivate dalla classe Animale, e dunque ereditano le proprietà anzidette. Tuttavia, è possibile diversificare tali classi introducendo la funzione “Scodinzola” alla classe Cane e la funzione 81 “Miagola” alla classe Gatto. E’ indubbio che le due classi ereditano le proprietà della classe Animale, ma creano un polimorfismo in quanto esse si diversificano dalla prima e tra di loro. 4.1.2 Cenni di caratteristiche avanzate del linguaggio Delphi In Delphi è possibile implementare Eventi e caratteristiche particolari delle proprietà. Le proprietà in delphi possono essere semplici variabili o possono avere della caratteristiche più complesse. Di seguito alcuni esempi 1. Property Variabile; 2. Property Variabile: string Read FVariabile; 3. Property Variabile: string Write FVariabile; 4. Property Variabile: string Read GetVariabile; 5. Property Variabile: string Write SetVariabile; 6. Property Variabile: string Read GetVariabile Write SetVariabile; Il primo esempio, il quale non dichiara il tipo, viene utilizzato, generalmente, per modificare la visibilità di un campo ereditato da una classe genitrice. Il secondo, dichiara una variabile di tipo string che è possibile soltanto leggere e non scrivere. Questo approccio si usa tipicamente per ottenere uno stato interno di una classe leggendo un campo incapsulato alla classe e non modificabile dall’esterno di essa, ma usato solo dalla classe stessa. 82 Il terzo esempio, permette di scrivere soltanto in una variabile interna, generalmente utilizzato in combinazione con altri esempi sopra riportati. Il quarto approccio dichiara una Variabile di tipo stringa la quale è il risultato di una funzione dello stesso tipo. Viene utilizzato, generalmente, per fornire un risultato in accordo ad alcune variabili e comportamenti in cui la classe si trova e non è possibile modificare il suo contenuto. Questo è un caso di programmazione degli oggetti fortemente incapsulata e che implementa delle proprietà denominate “fake” o “false”, poiché si ha l’illusione di leggere direttamente da campi interni, mentre in realtà ciò non avviene. Il quinto approccio, che è la combinazione del quarto e quinto esempio, dichiara una variabile di tipo stringa la quale in lettura, fornisce il risultato di una funzione ed in scrittura memorizza direttamente il valore in un campo incapsulato. Questo approccio è utilizzato in particolari contesti quando non si vuole permettere allo sviluppatore di interagire direttamente con il campo privato della classe, ma solo in accordo a ciò che le funzioni implementano. Ovviamente, i precedenti casi possono essere combinati, come nel quinto esempio. 4.1.3 Gli Eventi Gli Eventi altro non sono che proprietà particolari degli oggetti dichiarati come Tipi. Ad esempio, il tipo 83 Type TNotifyEvent = procedure(Sender: TObject) of object; crea una proprietà di tipo TNotifyEvent dichiarato come una procedura di un oggetto che ammette un parametro TObject, ovvero una classe dal quale tutti i controlli e i componenti derivano. Gli eventi, dunque, vengono chiamati in base ad alcune implementazioni delle classi che rispondono a particolari Messaggi inviati dai sistemi operativi all’applicazione o ad alcune modifiche sull’istanza di una classe. A seconda del tipo di messaggio ricevuto e se l’evento della classe istanziata punta ad una procedura di tipo TNotifyEvent implementata allora la classe richiama la procedura stessa. Questo determina alcuni comportamenti che sono forniti alla classe in fase di sviluppo e che possono essere modificati in fase di esecuzione dell’applicativo. 4.1.4 Sovrascrittura delle funzioni e procedure ereditate Come già detto, quando una classe deriva da un’altra classe la prima eredita tutte le caratteristiche, le proprietà, i metodi e i comportamenti della seconda classe. In alcuni contesti, soprattutto nei casi di polimorfismo, alcuni metodi vengono sovrascritti con la keyword “Override”. Ciò permette di richiamare univocamente la nuova procedura e la chiama. In altri contesti, la nuova procedura viene creata semplicemente per inserire alcuni comportamenti aggiuntivi, anziché modificarne altri. Ad esempio, se la classe A è dichiarata nel seguente modo 84 Type Classe_A = class Public Variabile: String; Procedure Scrivi; Procedure Paint(X,Y: Integer); End; la classe B la si può dichiarare nel seguente modo Type Classe_B = class(Classe_A) Public Procedure Paint(X,Y: Integer); override; End; Con questa dichiarazione di classe, facciamo sì che la classe B sovrascriva la procedura Paint(X,Y: Integer) soltanto se viene richiamata dalla classe B. E’ utile notare che la Classe_B eredita sia Variabile che la procedura Scrivi in quanto la classe è derivata dalla Classe_A e non necessita di dichiarare nuovamente sia la variabile che la procedura. Comunque, è possibile, tuttavia, recuperare l’intera procedura della classe ereditata qualora si inserisca nella procedura Paint della classe B la dicitura “Inherited”. Il seguente esempio è chiarificatore 85 Procedure Classe_B.Paint(X,Y: Integer); begin Inherited Paint(X,Y); … End; così scrivendo è possibile recuperare la procedura della classe ereditata ed è possibile estenderla inserendo ulteriore codice sostituendolo ai puntini e senza andare a modificare la classe genitrice. Come si evince, questa capacità del linguaggio è molto utile nei casi di polimorfismo dove una classe deriva da una classe base sulla quale vengono implementate alcune caratteristiche e comportamenti che devono essere comuni a tutte le classi che ne derivano. 4.1.5 Visibilità delle proprietà e metodi e semplici tecniche di Hacking Nelle classi, le proprietà e i metodi hanno una caratteristica denominata visibilità. Questa rende visibile le proprietà e i metodi che possono essere visualizzati da altri files che compongono l’applicativo. Le visibilità, nel linguaggio Delphi, sono quattro: Private, Protected, Public e Published. Si vuole indicare con Private quelle variabili, funzioni e procedure che generalmente sono da ausilio alla classe in sé e che comportano 86 l’implementazione interna della classe, ma non alle classe che derivano da questa. Con la keyword Protected, si intende specificare che i campi, le proprietà e i metodi, dichiarati in questo modo, possono essere visualizzabili soltanto dalla classe che le implementa e dalle classi che ne derivano, su quest’ultime attuando una tecnica di Hacking sulla classe genitrice. Con la dicitura Public, si intende rendere pubbliche quei campi, metodi e proprietà ai files esterni all’implementazione della classe e tutte le altre classi che non derivano dalla classe implementante. Con la dicitura Published, si fornisce all’ambiente di sviluppo Delphi, la capacità di poter modificare alcune caratteristiche della classe nella fase di Design Time dell’implementazione di un generico programma. Per l’applicativo della tesi, si sono utilizzate le visibilità Private, Protected e Public. In alcuni contesti è indispensabile usare delle tecniche particolari del linguaggio Delphi, quelle di hacking, per recuperare alcuni campi o modificare alcuni metodi, durante la fase di sviluppo del programma, per rendere accessibili classi non visibili. Se, ad esempio, una classe A dichiara una variabile come Private come segue Type Classe_A = class Private Variabile: Integer; end; 87 l’unico modo di rendere accessibile tale variabile è quello di derivare una classe da Classe_A e di dichiarare la Variabile in maniera Public. Il procedimento è mostrato come segue Type Classe_B = class(Classe_A) Public Variabile: Integer; end; Per utilizzare, dunque, la Variabile è necessario eseguire un Type Casting sulla classe derivante. Quindi, avendo derivato una Classe_C dalla Classa_A, la tecnica di hacking, per modificare la Variabile, prende la seguente forma Classe_B(Classe_C).Variabile := 10; Con questa tecnica, si rende rendono visibili alcuni campi e metodi importanti per l’implementazione delle classi, eseguendo una corretta e buona incapsulazione delle classi, senza stravolgere le classi e senza rendere insicuro il comportamento di queste. Per l’implementazione del programma si è reso necessario utilizzare tale caratteristica del linguaggio in alcuni contesti. 88 4.2 Implementazione del Framework Iconico Per la rappresentazione iconica del framework, si sono creati alcuni oggetti. Questi oggetti sono classi che derivano da un’altra classe base definita TForme, la quale deriva da un’altra classe TGraphicControl che fornisce quelle che vengono definite “Regioni” dove poter disegnare le varie icone e fornisce una serie di strumenti, per la realizzazione dei disegni, definiti in una sua classe, incapsulata, chiamata Canvas. Nel seguito si fornisce la definizione ed una descrizione delle caratteristiche rilevanti delle varie classi implementate per il framework. 4.2.1 Classe TForme Di seguito vengono fornite la descrizione e le principali parti della classe TForme. TForme = class(TGraphicControl) private FPen: TPen; FBrush: TBrush; FEtichetta: TLabel; FShape: TForma; FCaption: String; FonUserDraw: TonUserDraw; FbyUser: boolean; FCodice: String; FEtichetta_Visibile: Boolean; 89 FLivello_Annidamento: Integer; FColore_Bordo: TColor; FSelezionato: Boolean; procedure DrawEllipse; procedure DrawRectangle; procedure DrawRoundRect; procedure DrawArrow; procedure SetCaption(const Value: String); procedure DrawText; procedure DoUserDraw; procedure SetLivello_Annidamento(const Value: Integer); procedure SetColore_Bordo(const Value: TColor); procedure SetSelezionato(const Value: Boolean); procedure SettaEtichetta(Value: TLabel); protected procedure Paint; override; public FEtichetta: TLabel; Connessioni: array[Low(TLati)..High(TLati)] of Tpoint; Baricentro: TPoint; Connessioni_Precedenti:array of TForme; Connessioni_Post:array of TForme; Connessioni_Trasversali_Precedenti: array of TForme; Connessioni_Trasversali_Post: array of TForme; Linkers: array of TLinker; Nome : String; Colore_Bordo_Default: TColor; constructor Create(AOwner: TComponent); override; destructor Destroy; override; procedure Calcola_Dati; property Canvas; property Colore_Bordo: TColor read FColore_Bordo write SetColore_Bordo; property Selezionato: Boolean read FSelezionato write SetSelezionato; property Codice: String read FCodice write SetCodice; property Etichetta: TLabel read FEtichetta write SettaEtichetta; 90 property Livello_Annidamento: Integer read FLivello_Annidamento write SetLivello_Annidamento; procedure Individua_Linker_Partenza(var Linker:TLinker; Destinazione:TForme); procedure Individua_Linker_Arrivo(var Linker:TLinker; Arrivo:TForme); procedure Collega_Avanti(var Destinazione: TForme); procedure Scollega_Avanti; procedure Scollega_Indietro; procedure Scollega_Trasversale; procedure Collega_Trasversale_Avanti(var Destinazione: TForme; Tipo_Collegamento: TTipi_Collegamenti); procedure Aggiorna_Codice; procedure Salva_Xml(var Nodo: IXMLNode); procedure Carica_Xml(var Nodo: IXMLNode); procedure Cancella_Linker(var Linker: tlinker); procedure Cancella_Linker_Avanti(var Linker: tlinker); procedure Cancella_Linker_Indientro(var Linker: tlinker); procedure Cancella_Linker_Trasversale(var Linker: tlinker); function Linker_By_Nome(var Linker: TLinker; Nome: String): Boolean; property Etichetta_Visibile: Boolean read FEtichetta_Visibile write SetEtichetta_Visibile; property Caption:String read FCaption write SetCaption; Come si evince vi sono vari campi e metodi definiti con visibilità diverse. Si discuterà, inizialmente, di ciò che viene definito come Private. Fpen ed FBrush sono le classi, incapsulate, specializzate nel disegnare, rispettivamente, il contorno e il riempimento dell’icona. FShape è definito come un tipo TForma, dichiarato come TForma = (TF_Rettangolo, TF_Quadrato, TF_Rettangolo_Arrotondato, TF_Quadrato_Arrotondato, TF_Ellisse, TF_Cerchio, F_Triangolo_Destra, TF_Triangolo_Su, TF_Triangolo_Sinistra, TF_Triangolo_Giu, TF_Rombo, TF_Ottagono,TF_Esagono); 91 FCaption, di tipo stringa, è la variabile che memorizza il contenuto da dover scrivere sopra l’icona. FonUserDraw e FbyUser sono, rispettivamente, l’evento per disegnare la forma della funzione, se l’utente desidera inserire una immagine per definire una propria funzione, ed FbyUser è una variabile booleana che indica se l’utente vuole che la funzione creata abbia una immagine personalizzata. FCodice, di tipo Stringa, è la stringa che identifica il codice associato all’icona. Questo viene FEtichetta_Visibile, di tipo booleano, indica se si vuole rendere visibile un commento per l’icona. FLivello_Annidamento, di tipo intero, è un valore importante per l’interfaccia grafica. Fornisce il livello di annidamento delle varie icone. FColore_Bordo, di tipo TColor ovvero un intero, indica il colore del bordo dell’icona. FSelezionato, di tipo booleano, indica se, durante l’interazione con l’applicativo, l’utente ha selezionato o meno l’icona. Le procedure DrawEllipse, DrawRectangle, DrawRoundRect, DrawArrow, DoUserDraw implementano la visualizzazione della grafica delle icone. La procedura DrawText implementa la visualizzazione del testo all’interno delle icone, e viene chiamata dopo le procedure che disegnano le varie forme delle icone. La procedura SetLivello_Annidamento accetta come input un valore intero e setta FLivello_Annidamento al suo valore. Contestualmente, aggiorna tutte le icone collegate ad essa. Le icone ad essa collegate sono aggiornate automaticamente. 92 La procedura SetColore_Bordo richiede un valore di tipo TColor. Questa procedura, oltre a settare il corrente valore di FColore_Bordo cambia il bordo dell’icona invocando la procedura Paint, discussa nel seguito. La procedura SetSelezionato, che richiede un valore booleano in ingresso, setta la variabile FSelezionato al valore attuale e contestualmente cambia il bordo e il riempimento dell’icona invocando la Paint. La procedura SettaEtichetta modifica l’etichetta associata all’icona. Questa Etichetta, un oggetto TLabel, descrive i commenti che l’utente vuole rendere noti. L’unica procedura Protected riguarda la procedura Paint. Questa è definita come override, in quanto la si vuole interamente modificare rispetto alla procedura Paint del TGraphicControl. La procedura è molto importante in quanto, inizialmente, esegue alcuni calcoli per definire le dimensioni che FPen e FBrush che devono rispettare e conseguentemente anche il Canvas. Successivamente, in accordo al tipo di valore di FShape vengono invocate le procedure che disegnano la forma dichiarata in FShape. A seguire, viene invocata la procedura DrawText che scrive il testo dichiarato in FCaption. Viene, poi, chiamato il metodo Calcola_Dati, spiegato nei dettagli successivamente, che calcola alcuni valori per i collegamenti con le altre icone. Nel seguito del paragrafo, si discuterà delle dichiarazioni pubbliche della classe. La variabile Connessioni è un array di TPoint, il quale è un record di due variabili: X e Y di tipo intero. Connessioni serve per specificare quali saranno i punti nel quale gli archi del flusso del programma saranno incidenti all’icona. 93 Un’altra variabile importante è Baricentro, anch’essa di tipo TPoint. Questa serve a memorizzare il baricentro dell’immagine. Questo dato sarà utilizzato dagli archi per creare visualmente e dinamicamente i collegamenti, in base alle posizioni in cui si troveranno due immagini, anche quando verranno spostate dall’utente. Le variabili Connessioni_Precedenti, Connessioni_Post, , Connessioni_Trasversali_Precedenti, Connessioni_Trasversali_Post sono degli array di tipo TForme. Gli elementi di questi array corrispondono alle altre icone con le quali sono direttamente collegate alle istanze della classe. Gli elementi di questi array sono molto importanti per la continuità del flusso e per la generazione del codice sorgente attraverso il codice iconico. La variabile Linkers è un array di tipo TLinker. E’ una variabile fondamentale per il concetto di flusso iconico, questa verrà introdotta nel prosieguo. Il campo Nome, di tipo string, permette di identificare univocamente le icone. Viene settato alla creazione di ogni istanza della classe. La variabile Colore_Bordo_Default, di tipo TColor, fornisce un colore di default nel caso si voglia cambiare e successivamente reimpostare il colore del bordo. Il valore della variabile è settato alla creazione di ogni istanza della classe derivante da TForme. La procedura Create, che ammette un input di tipo TComponent ovvero il proprietario dell’istanza della classe, è dichiarato come override e constructor. La dichiarazione constructor è una procedura richiamabile da qualunque classe non ancora instanziata e permette la creazione dell’istanza. Questa procedura inizializza molte variabili quali Nome, FEtichetta, FPen, FBrush FbyUser, 94 FEtichetta, i Linkers, FFLivello_Annidamento, Colore_Bordo_Defaul e Colore_Bordo, oltre alle dimensioni dell’icona di default. La procedura Destroy è dichiarata come override e come destructor. Le procedure destructor sono procedure chiamate automaticamente da ogni classe, in Delphi, è consentono di eseguire alcune operazioni prima che l’istanza della classe venga definitivamente eliminata e che la memoria, occupata dalla classe, venga liberata. In questa procedura vengono soltanto invocate le procedure per liberare la memoria dalle altre classi incapsulate dalla classe TForme. La procedura Calcola_Dati, come già accennato, è importante per la visualizzazione e l’automatismo grafico degli archi, chiamati Linkers. In questa procedura vengono aggiornati il Baricentro e l’array delle Connessioni, entrambi già discussi. Vedremo successivamente che questi parametri sono fondamentali per fornire agli archi il giusto orientamento. La proprietà Canvas è l’oggetto specializzato a disegnare sulla Regione fornita dal TGraphicControl e viene chiamato ogni qualvolta sia necessario disegnare o scrivere. La proprietà Colore_Bordo setta il bordo dell’icona richiamando implicitamente la procedura SetColore_Bordo che serve a modificare FColore_Bordo. La proprietà Selezionato richiama la procedura SetSelezionato, questa setta FSelezionato a True quando l’icona è selezionata e contestualmente modifica lo spessore ed il colore del bordo dell’icona; oppure setta FSelezionato a False, rendendo normale lo spessore dell’icona ed anche il suo colore. La proprietà Codice richiama la procedura SetCodice che setta il valore di FCodice a Codice. 95 La proprietà Etichetta invoca implicitamente la procedura SettaEtichetta la quale permette di gestire l’istanza FEtichetta dell’oggeto TLabel, incapsulato in TForme. La proprietà Livello_Annidamento SetLivello_Annidamento che setta il invoca corretto valore la procedura alla variabile FLivello_Annidamento, già discussa, e aggiorna tutti i valori di tutte le icone che discendono dall’istanza della classe. Questo è molto utile e potente, quanto semplice, in quanto ogni icona che avrà modificato il proprio livello di annidamento, modificherà le icone ad essa collegate, in cascata ed in maniera automatica. La procedura Individua_Linker_Partenza, che ammette come dati in input un Linkers di tipo TLinkers ed una Destinazione di tipo TForme, serve per rintracciare quale icona è collegata all’arco incidente a Destinazione, ovvero da quale icona parte l’arco che punta verso Destinazione. La procedura Individua_Linker_Arrivo, che ammette come dati in input un Linkers di tipo TLinkers ed una Arrivo di tipo TForme, serve per rintracciare quale icona è collegata all’arco uscente ad Arrivo, ovvero verso quale icona finisce l’arco che parte da Arrivo. La procedura Collega_Avanti, ammette come dato in input una variabile Destinazione di tipo TForme. Tale procedura crea fisicamente il legame tra due icone ed individua la direzione del flusso. Il legame, o relazione, tra le due icone è consentito soltanto se l’icona di destinazione non ha archi incidenti su essa e se l’icona di partenza non ha già un suo successore nel flusso. Dopo aver collegato le icone, la procedura invoca la procedura Calcola_Dati sia per l’icona di partenza che per quella di destinazione al fine di aggiornare i dati, ovvero le 96 coordinate, utili all’orientamento degli archi. Alla fine, viene invocata la procedura Aggiorna_Linker dell’arco appena creato, discussa nel prosieguo. La procedura Scollega_Avanti elimina fisicamente un collegamento tra un’icona ed un’altra, aggiornando gli archi di entrambe le icone. La procedura Scollega_Indietro richiama la procedura Scollega_Avanti se l’icona ha un predecessore nel flusso, altrimenti la procedura si ferma. La procedura Destionazione di Collega_Trasversale_Avanti, tipo TForme e un richiede in input Tipo_Collegamento di una tipo TTipi_Collegamenti, quest’ultimo può assumere uno dei seguenti valori TTC_Avanti, TTC_Begin, TTC_Ciclo, TTC_IF_Then, TTC_IF_ELSE, TTC_Case. Ognuno di questi valori corrisponde a casi distinti di collegamenti nel flusso. Un collegamento trasversale avviene ogni qual volta vi è un cambiamento di livello di annidamento nel flusso. Poiché un’icona può avere collegato in entrata solo un arco trasversale, eccezion fatta per le icone Etichetta, e in uscita solo un arco trasversale, eccezion fatta per l’icona del Case. La procedura controlla se vi è possibilità di collegare le due icone verificando se nessuna delle due icone hanno collegamenti trasversali, eccezion fatta per i due casi precedenti. Quindi, la procedura collega trasversalmente le due icone, assegnando all’icona di Destinazione il livello di annidamento dell’icona di partenza aumentato di uno. In tale modo, aggiorna in cascata tutti i livelli di annidamento delle icone successive nel flusso a Destinazione. La procedura Scollega_Trasversale, scollega l’arco trasversale tra due icone, settando a 1 il livello di annidamento della icona che precedentemente era di 97 Destinazione, ed aggiornando così in cascata tutte le successive icone nel suo flusso. La procedura Aggiorna_Codice non è implementata in questa classe in quanto sarà sovrascritta in tutte le altre classi che derivano da TForme. E’ stata inserita in quanto poiché implementata dalle classi derivanti, questa richiama la procedura dichiarata ed implementata dalla classe corretta. Questo per evitare continui Type Casting sulle varie icone. La procedura Salva_Xml, riceve in input un’interfaccia IXMLNode, la quale fornisce un’interfaccia per salvare i dati dell’icona in formato xml. La procedura crea un nodo Figura attraverso l’interfaccia ed scrive una serie di attributi XML in maniera tale da memorizzare sia le informazioni utili al recupero dello stato dell’icona, sia informazioni legate al flusso dei dati, ovvero gli archi incidenti ed uscenti dall’icona. La procedura Carica_Xml, ricevere anch’essa un’interfaccia IXMLNode. Questa è la procedura duale a Salva_Xml, ovvero recupera dagli attributi XML tutti i dati necessari a ripristinare lo stato salvato dell’icona e le informazioni inerenti il flusso. La procedura Cancella_Linker, richiede in input un Linker di tipo TLinkers. Tale procedura serve per aggiornare la lista degli archi incidenti ed uscenti da un’icona. Questa procedura viene creata poiché si vuole evitare la ridondanza di codice in quanto viene utilizzata è dalle una porzione procedure di codice che Cancella_Linker_Avanti, Cancella_Linker_Indientro e Cancella_Linker_Trasversale, le quali eliminano, rispettivamente, gli archi in avanti, indietro e trasversalmente al flusso. 98 La procedura Linker_By_Nome, riceve in input un Linker di tipo TLinker e una variabile Nome di tipo stringa. Questa procedura restituisce l’arco, assegnandolo a Linker, che collega l’icona ad un’altra icona di nome Nome. La proprietà Etichetta_Visibile richiama la procedura SetEtichetta_Visibile la quale rende visibile o meno FEtichetta. Infine, la proprietà Caption invoca la procedura SetCaption che oltre a modificare la variabile FCaption ridisegna l’icona inserendo come testo il valore di Caption. 4.2.2 Classe TFigura_Start La classe TFigura_Start deriva dalla classe TFigure che deriva da TForme. TFigure è solo una classe di intermezzo senza modifiche, usata per verifiche di Type Casting dal programma. Grazie all’ereditarietà delle classi, questa riceve in eredità tutte le proprietà, i campi e i metodi implementati nella classe genitrice. La descrizione della classe assume la seguente forma TFigura_Start = class(TFigure) public constructor Create(AOwner: TComponent); override; procedure Salva_Xml(var Xml: TXMLDocument; var Nodo: IXMLNode); procedure Carica_Xml(var Nodo: IXMLNode); end; 99 la procedura Create, è dichiarata come override. All’interno della procedura viene richiamata la procedura Create ereditata, e successivamente modifica altezza e larghezza dell’immagine. Viene anche modificata, la forma agendo sulla proprietà Shape che in automatico assicura la corretta icona. Successivamente, vengono inizializzate tutte le altre proprietà quali i colori del bordo e del riempimento e del Font utilizzato per scrivere sull’icona. Viene anche richiamata la procedura Calcola_Dati che assicura di avere i corretti punti di giunzione tra gli archi e il Baricentro. La procedura procedura Salva_Xml, ammette come dati due classi di interfaccia XML. La prima corrisponde al progetto e la seconda corrisponde al nodo in cui verranno scritti i dati per recuperare le posizioni dell’icona e l’arco uscente da essa. La procedura Carica_Xml, ammette come dato in ingresso un’interfaccia al nodo dal quale bisogna recuperare i dati e setta le variabili della classe per il riposizionamento e il possibile collegamento ad un’altra icona, per il flusso. 4.2.3 Classe TFigura_Dato La classe TFigura_Dato, come le altre icone, deriva da TFigure. Essa serve a memorizzare le variabili e le costanti all’interno di una funzione o procedura. La descrizione della classe è la seguente TFigura_Dato = class(TFigure) public Tipo_Dato: TDato_Matrice; 100 constructor Create(AOwner: TComponent); override; destructor Destroy; override; procedure Aggiorna_Codice; procedure Salva_Xml(var Xml: TXMLDocument; var Nodo: IXMLNode); procedure Carica_Xml(var Nodo: IXMLNode); end; La variabile Tipo_Dato è una classe che identifica i tipi di dato e verrà spiegata successivamente. La procedura Create, anch’essa è descritta come override ed invoca la procedura genitrice. Inoltre, inizializza alcuni parametri atti ad identificare cognitivamente il tipo di costrutto, fornendo una chiara forma e colore in base al tipo di dato che memorizza. Esegue anche la creazione e la inizializzazione della variabile Tipo_Dato e richiama la procedura Calcola_Dati. Tale procedura, in tutte le classi derivate da TForme, deve essere necessariamente chiamata dalla sub-classe in quanto essa stessa identifica la forma e le dimensioni dell’icona e quindi deve anche assumersi il compito di calcolare i dati di congiunzione degl’archi e del Baricentro. La procedura Destroy, dichiarata come override, libera la memoria usata dalla classe Tipo_Dato e invoca la procedura Destroy ereditata da TForme. La procedura Aggiorna_Codice non è dichiarata come override, in quanto la classe genitrice ha una procedura vuota, quindi non è necessario sovrascriverla. Questa procedura esegue una serie di controlli sulla variabile Tipo_Dato e, nel caso in cui tutti i dati di quest’ultimo siano completi, viene generato il codice sorgente in linguaggio C in accordo ai dati inseriti in Tipo_Dato. 101 La procedura Salva_Xml, ammette come dati due classi di interfaccia XML. La prima corrisponde al progetto e la seconda corrisponde al nodo in cui verranno scritti i dati in Tipo_Dato. Inoltre, richiama la procedura richiama Salva_Xml della classe genitrice, che serve a memorizzare tutte le variabili utili alla rappresentazione visiva dell’icona e dei suoi archi. La procedura Carica_Xml, accetta come input l’interfaccia IXMLNode che fornisce i dati al recupero di tutti valori di Tipo_Dato e alle posizioni dell’icona e dei suoi collegamenti, anche richiamando la procedura ereditata. 4.2.3.1 Classe TTipo_Dato Questa classe implementa la classe base per TDato_Matrice. Essa consiste di tutte le informazioni utili all’identificazione del dato, variabile o costante, il tipo di variabile, il suo nome e il suo valore, nel caso di costanti o variabili inizializzate. La sua definizione assume la seguente forma TTipo_Dato = class public Nome: String; Tipo_Di_Dati: TTipi_di_Dati; Tipo_Di_Shape: TTipi_Variabile; Stringa_Tipo_Di_Dati: String; Stringa_Tipo_Di_Shape: String; Valore: String; procedure Salva_Parametro(var Xml: TXMLDocument; var Nodo: IXMLNode); procedure Carica_Parametro(var Xml: TXMLDocument; var Nodo: IXMLNode); End; 102 La variabile Nome, di tipo stringa, consiste nel nome, o simbolo, che si fornisce alla variabile. La variabile Tipo_Di_Dati, di tipo TTipi_di_Dati, assume un valore di un insieme enumerabile definito come TD_Sconosciuto, TD_Void, TD_Char, TD_int, TD_short, TD_long, TD_long_long, TD_float, TD_double, TD_Funzione, ovvero i tipi primitivi che si possono incontrare nel linguaggio C, aggiunto da un tipo sconosciuto e dal tipo funzione. La variabile Tipo_Di_Shape, di tipo TTipi_Variabile, assume un valore nel seguente insieme TTS_Sconosciuto, TTS_Costante, TTS_Variabile, ovvero descrive se la il dato è una costante o una variabile, oppure un tipo sconosciuto. La variabile Stringa_Tipo_Di_Dati assume un valore stringa, comprensibile all’utente, che è in accordo alla variabile Tipo_Di_Dati. La variabile Stringa_Tipo_Di_Shape, di tipo stringa, assume un valore in accordo a Tipo_Di_Shape. La variabile Valore, anch’essa di tipo stringa, coincide col valore del dato dichiarato, nel caso di costante o di variabile inizializzata. La procedura Salva_Parametro riceve in input, come le altre classi, le interfacce per salvare i valori sopra discussi. Questi verranno recuperati con la procedura Carica_Parametro e inseriti nelle rispettive variabili. 103 4.2.3.2 Classe TDato_Matrice Questa è una classe che implementa una serie di metodi e proprietà atte ad individuare le dimensioni del dato e a memorizzarle attraverso una forte incapsulazione. Deriva dalla classe TTipo_Dato, dalla quale ne riceve tutte le variabili e le procedure. E’ descritta come segue TDato_Matrice = class(TTipo_Dato) private FArray_Dimensioni: array of Integer; FDimensioni: Integer; procedure SetDimensioni(const Value: Integer); function GetArray_Dimensioni(Index: Integer): Integer; procedure SetArray_Dimensioni(Index: Integer; const Value: Integer); public property Array_Dimensioni[Index: Integer]: Integer read GetArray_Dimensioni write SetArray_Dimensioni; property Dimensioni: Integer read FDimensioni write SetDimensioni; procedure Salva_Parametro(var Xml: TXMLDocument; var Nodo: IXMLNode); procedure Salva_Parametro(var Nodo: IXMLNode); constructor Create; destructor Destroy; end; la variabile FArray_Dimensioni è un array di tipo intero. Questa definisce la grandezza di ogni dimensione del dato. Non viene direttamente manipolata dall’utente, ma è fortemente incapsulata e i suoi dati vengono manipolati da GetArray_Dimensioni e da SetArray_Dimensioni che ricevendo in input il valore di Index, un intero, restituiscono o modificano il valore in accordo alla 104 loro implementazione. L’utente ha la sensazione di manipolarle direttamente quando si interagisce con la variabile pubblica Array_Dimensioni, che in realtà richiama le sopra dette procedure e funzioni. La variabile FDimensioni, di tipo intero, setta la dimensione dell’array FArray_Dimensioni attraverso la procedura SetDimensioni invocata implicitamente quando si modifica la variabile Dimensioni. La procedura Salva_Paramentro, come tutte le altre classi, accetta le interfacce XML per salvare sia le variabile del tipo di classe genitrice sia le variabili proprie. La procedura Carica_Parametro, riceve in input un’interfaccia IXMLNode e la usa recuperando i valori delle variabili memorizzate precedentemente con Salva_Parametro. La procedura Create costruttrice della classe, diversamente dai precedenti casi, non è dichiarata come override. Questo poiché dalla classe genitrice non era necessario andare ad implementarla, dunque non è necessario e né possibile andare a sovrascriverla. Questa procedura inizializza le variabili in maniera opportuna e setta la lunghezza di FArray_Dimensioni a zero. La procedura Destroy elimina la classe, ed è necessaria implementarla in quanto essa libera la memoria dell’array FArray_Dimensioni. 105 4.2.4 Classe TFigura_Ciclo La classe TFigura_Ciclo serve a configurare la dichiarazione di un ciclo nel codice sorgente in C. La classe, come le altre, deriva da TFigure ed ha la seguente forma dichiarativa TFigura_Ciclo= class(TFigure) private FTipo_Ciclo: TTipi_Ciclo; procedure SetTipo_Ciclo(const Value: TTipi_Ciclo); public Condizioni: TCondizione; Variabile: String; Valore: String; Espressione: String; constructor Create(AOwner: TComponent); override; destructor Destroy; override; procedure Aggiorna_Codice; property Tipo_Ciclo: TTipi_Ciclo read FTipo_Ciclo write SetTipo_Ciclo; procedure Salva_Xml(var Xml: TXMLDocument; var Nodo: IXMLNode); procedure Carica_Xml(var Nodo: IXMLNode); end; La variabile privata FTipo_Ciclo assume uno dei seguenti valori enumerabili TTC_For, TTC_While, TTC_Repeat, e serve ad indicare il tipo e la forma del ciclo nel codice sorgente in C, in accordo alle forme di dichiarazione in C. La procedura privata SetTipo_Ciclo, che richiede in input un valore TTipi_Ciclo, viene richiamata implicitamente quando si modifica la proprietà publica Tipo_Ciclo. Tale procedura, oltre a modificare la variabile FTipo_Ciclo, 106 modifica anche il colore del riempimento dell’icona in accordo al colore associato al valore di FTipo_Ciclo. Inoltre, modifica anche il testo all’interno dell’icona per fornire un immediata comprensione cognitiva del ciclo utilizzato all’utente finale. La variabile Condizioni è una classe di tipo TCondizione, tale classe verrà spiegata nel seguito. Questa variabile memorizza tutte le condizioni alle quali Variabile è soggetta per la continuazione del ciclo. La variabile Variabile, di tipo stringa, assume il nome della variabile assegnata come contatore da utilizzare all’interno del ciclo. La variabile Valore, di tipo stringa, è il valore iniziale che Variabile avrà assegnato all’interno del ciclo, se si utilizza come Tipo_Ciclo il valore TTC_For. La variabile Espressione, di tipo stringa, fornisce l’espressione di incremento che agisce su Variabile nel caso di un ciclo For. La procedura costruttiva Create, dichiarata come override, inizializza tutte le variabili e anche l’istanza di classe Condizioni, oltre ad invocare la omonima procedura genitrice. Mentre la procedura distruttiva di classe Destroy, dichiarata anch’essa come override, libera la memoria usata dall’istanza della classe Condizioni e invoca la procedura omonima genitrice. La procedura Aggiona_Codice, in base ai valori delle singole variabili, crea il codice del ciclo e lo struttura in maniera tale che sia in accordo con le tipologie dei costrutti del linguaggio C, in base al tipo di valore memorizzato in FTipo_Ciclo. 107 Le procedure Salva_Xml e Carica_Xml, come nei precedenti casi, ricevono in input delle interfacce XML che servono, rispettivamente alle procedure, per salvare tutti i dati memorizzati all’interno dell’istanza della classe e per recuperare e settare i valori salvati nell’istanza della classe. 4.2.4.1 Classe TCondizione La classe TCondizione permette di memorizzare le varie condizioni, o espressioni booleane, e i relativi connettori logici tra queste. Tale classe verrà utilizzata anche in altre classi derivate da TFigure. Questa classe memorizza soltanto i valori e non crea codice in C. La classe è definita nella seguente forma TCondizione = class Public Negazioni: array of boolean; Condizioni: array of String; Oper_Logici: array of String; constructor Create; destructor Destroy; procedure Salva_Parametro(var Xml: TXMLDocument; var Nodo: IXMLNode); end; La variabile Negazioni è un array di valori booleani, i quali servono a riferire se si deve considerare la negazione delle singole condizioni oppure il valore originario. 108 La variabile Condizioni è un array di stringhe, dove vengono memorizzate tutte le condizioni usate. La variabile Oper_Logici è anch’essa un array di stringhe dove si memorizzano tutti gli operatori logici usati per connettere le varie condizioni, o espressioni booleane. 4.2.5 Classe TFigura_If_Then_Else La classe TFigura_If_Then_Else realizza l’omonimo costrutto. La forma dichiarativa è la seguente TFigura_If_Then_Else= class(TFigure) public Condizioni: TCondizione; constructor Create(AOwner: TComponent); override; destructor Destroy; override; procedure Aggiorna_Codice; procedure Salva_Xml(var Xml: TXMLDocument; var Nodo: IXMLNode); procedure Carica_Xml(var Nodo: IXMLNode); end; La variabile Condizioni assume la stessa funzione esposto nella classe TFigura_Ciclo, solo che viene usato per il costrutto If..Then..Else. La procedura costruttiva Create, dichiarata come override, inizializza l’istanza di classe Condizioni, oltre ad invocare la omonima procedura genitrice. 109 La procedura distruttiva di classe Destroy, dichiarata anch’essa come override, libera la memoria usata dall’istanza della classe Condizioni e invoca la procedura omonima genitrice. La procedura Aggiona_Codice è molto importante in quanto costruisce il codice sorgente partendo dalle condizioni fornite. Le procedure Salva_Xml e Carica_Xml, come nei precedenti casi, ricevono in input delle interfacce XML che servono, rispettivamente alle procedure, per salvare tutti i dati memorizzati all’interno dell’istanza della classe e per recuperare e settare i valori salvati nell’istanza della classe. 4.2.6 Classe TFigura_Blocco La classe TFigura_Blocco fornisce un semplice modo per inserire blocchi di codice aggiuntivi. La classe deriva, come le altre classi iconiche, da TFigure ed assume la seguente forma dichiarativa TFigura_Blocco = class (TFigure) public Stringhe: array of String; Numero_Stringhe: Integer; constructor Create(AOwner: TComponent); override; destructor Destroy; override; procedure Salva_Xml(var Xml: TXMLDocument; var Nodo: IXMLNode); procedure Carica_Xml(var Nodo: IXMLNode); end; 110 La variabile Stringhe, un array di tipo stringa, memorizza le stringhe inserite dall’utente. Mentre, la variabile Numero_Stringhe, di tipo intero, corrisponde alla cardinalità dell’array, ovvero al numero di stringhe inserite. Il costruttore Create, come negl’altri casi, è dichiarato override, e serve per inizializzare l’array Stringhe e il valore Numero_Stringhe a zero, oltre che ad inizializzare le altre variaibili ereditate e a costruire l’immagine corretta dell’icona. Mentre il distruttore Destroy, anch’esso dichiarato override, serve per liberare la memoria dell’array Stringhe. 4.2.7 Classe TFigura_Break_Continue_Exit La classe TFigura_Break_Continue_Exit, è una classe iconica che fornisce informazioni circa la continuità o le interruzioni all’interno di una funzione. Deriva da TFigure ed ha la seguente forma dichiarativa TFigura_Break_Continue_Exit = class (TFigure) private FTipo: TTipi_Interruzioni; procedure SetTipo(Value: TTipi_Interruzioni); public property Tipo: TTipi_Interruzioni read FTipo write SetTipo; constructor Create(AOwner: TComponent); override; procedure Salva_Xml(var Xml: TXMLDocument; var Nodo: IXMLNode); procedure Carica_Xml(var Nodo: IXMLNode); 111 end; la variabile FTipo, di tipo TTipi_Interruzioni, assume uno dei seguenti valori TTI_Break, TTI_Continue, TTI_Exit, ed indica il tipo di codice che si andrà ad inserire. La procedura SetTipo modifica FTipo con il valore ricevuto in ingresso e contestualmente modifica anche l’immagine dell’icona e il suo testo, che rappresenta la scelta del tipo di informazione desiderato. Il costruttore Create, dichiarata come override, si comporta come nelle precedenti classi incontrate. Anche le procedure Salva_Xml e Carica_Xml hanno lo stesso comportamento delle altre classi incontrate. 4.2.8 Classe TFigura_Switch La classe TFigura_Switch è una classe che corrisponde al costrutto Switch..Case. Con questa classe si offre all’utente la possibilità di fornire più scelte, e quindi più comportamenti, ad una porzione di un algoritmo in base al risultato di un’espressione. La definizione della classe è la seguente TFigura_Switch = class(TFigure) public Espressione: String; Casi: array of String; constructor Create(AOwner: TComponent); override; 112 destructor Destroy; override; end; La variabile Espressione, di tipo stringa, memorizza l’omonima l’espressione dello costrutto Switch. La variabile Casi è un array di tipo stringa la quale memorizza le possibili diramazioni dello Switch. Tali diramazioni, devono essere in accordo con i possibili risultati dell’Espressione. Il costruttore Create, dichiarato override, oltre d invocare, come nelle altre classi, l’omonima procedura ereditata inizializza Espressione e Casi. Il distruttore Destroy, anch’esso override, libera la memoria dell’array Casi, oltre a chiamare il distruttore ereditato. 4.2.9 Classe TFigura_Assegnazione La classe TFigura_Assegnazione è una classe che fornisce un’icona più grande rispetto alle altre. Rappresenta l’assegnazione di una espressione ad una variabile. La classe deriva anch’essa da TFigure, e la sua dichiarazione è la seguente TFigura_Assegnazione = class(TFigure) private FTipo_Variabile: TTipi_di_Dati; procedure SetTipo_Variabile(Value: TTipi_di_Dati); public Espressione: String; 113 Variabile: String; property Tipo_Variabile: TTipi_di_Dati read FTipo_Variabile write SetTipo_Variabile; procedure Aggiorna_Codice; constructor Create(AOwner: TComponent); override; end; La variabile FTipo_Variabile, di tipo TTipi_di_Dati, memorizza internamente il tipo di variabile alla quale si assegnerà la variabile Espressione. La procedura Set Tipo_Variabile, richiede in input un tipo in accordo a FTipo_Variabile, e lo assegna ad essa. Inoltre, modifica l’aspetto dell’icona, in accordo sia al nome della variabile che al tipo. La variabile Espressione, di tipo stringa, indica l’espressione da assegnare a Variabile. Il campo Variabile, anch’esso di tipo string, identifica il nome della variabile assegnataria. La procedura Create, come nelle altre classi, è dichiarata override, e oltre ad invocare l’omonima procedura ereditata inizializza FTipo_Variabile ed altre variabili ereditate per la rappresentazione iconografica. La procedura Destroy non viene implementata, in quanto non vi è alcuna variabile che, alla distruzione dell’istanza della classe, non libera la memoria usata. 114 4.2.10 Classe TFigura_Funzione Anche tale classe deriva da TFigure. Questa classe rappresenta la funzione che viene richiamata nel flusso, senza necessità di assegnare un valore a qualche variabile. La sua dichiarazione è la seguente TFigura_Funzione = class(TFigure) public Include: String; Nome_Funzione: String; Tipo_Funzione: TTipi_di_Dati; Parametri: array of string; constructor Create(AOwner: TComponent); override; destructor Destroy; override; end; La variabile Include, di tipo stringa, identifica il file utilizzato dove risiede la funzione cercata. La variabile Nome_Funzione, di tipo stringa, definisce il nome della funzione desiderata. Invece, Tipo_Funzione, di tipo TTipi_di_Dati, identifica la tipologia di dato che la funzione fornisce in output. La variabile Paramentri, un array di tipo stringa, memorizza i parametri assegnati alla procedura. La procedura Create, sovrascritta a quella ereditata, che la richiama, inizializza Parametri definendo l’array con una lunghezza uguale a zero. 115 Mentre, il distruttore Destroy, anch’esso sovrascritto, libera la memoria di Parametri; 4.2.11 Classi TFigura_Label, TFigura_Goto, TFigura_Return, TFigura_Begin, TFigura_End Queste classi non implementano particolari proprietà in quanto sfruttano i campi e i metodi definiti in TForme. L’unica procedura che modificando è il costruttore Create, dichiarato override, in quanto alla creazione di ciascuna istanza, modificano opportunamente la loro forma e i loro colori, per rendere cognitivamente rappresentativo il significato delle loro icone. 4.3 Implementazione del flusso grafico: classe TLinker Il flusso può essere distinto in flusso grafico e flusso logico. Il flusso logico è implementato tramite gli array delle Connessioni implementate nella classe TForme. Mentre, il flusso grafico è costituito dagli archi, entranti o uscenti, dalle icone. La classe che implementa tali grafici è chiamata TLinker. La classe assume la seguente forma TLinker = class private FOggetto_Partenza: TForme; 116 FOggetto_Arrivo: TForme; Linee: array[0..2] of TForme; procedure SetOggetto_Partenza(const Value: TForme); procedure SetOggetto_Arrivo(const Value: TForme); procedure Disegna_Linker; public Lato_Partenza, Lato_Arrivo: TLati; Freccia_Partenza: TForme; Freccia_Arrivo: TForme; property Oggetto_Partenza: TForme read FOggetto_Partenza write SetOggetto_Partenza; property Oggetto_Arrivo: TForme read FOggetto_Arrivo write SetOggetto_Arrivo; constructor Create(Owner: Twincontrol); procedure Cancella; destructor Destroy; procedure Aggiorna_Linker; procedure Evidenzia_Linker; procedure Hide; procedure Show; end; Le variabili FOggetto_Partenza e FOggetto_Arrivo, di tipo TForme, costituiscono le icone, rispettivamente, di partenza e di arrivo dell’arco ed, attraverso esse, definiscono i punti dove l’arco verrà disegnato. La variabile Linee è un array di tipo TForme che costituisce le linee dell’arco. Le procedure SetOggetto_Partenza e SetOggetto_Arrivo ricevono in input i valori assegnati alle proprietà Oggetto_Partenza ed Oggetto_Arrivo. Le variabili Freccia_Partenza e Freccia_Arrivo, entrambi di tipo TForme definiscono le icone dell’arco rappresentate, rispettivamente, da un cerchio pieno dal quale parte l’arco e da una freccia verso il quale finisce l’arco. 117 Il costruttore Create, non dichiarato override in quanto la classe non deriva da alcun’altra classe, inizializza tutte le classi incapsulate in TLinker. La procedura Cancella richiama il distruttore Destroy, per eliminare l’arco. La procedura Destroy libera la memoria di tutte le classi incapsulate in Tlinker. La procedura Aggiorna_Linker è richiamata ogni qualvolta le icone dei costrutti vengono spostate e quando cambiano il loro livello di annidamento nel flusso. Questa procedura richiama Disegna_Linker e Evidenzia_Linker; La procedura Disegna_Linker è specializzata nel disegnare l’arco. Verifica il livello di annidamento dell’icona di arrivo e definisce il colore dell’arco in base a questo dato. Inoltre, a seconda delle posizioni del Baricentro delle Icone, definisce i punti di partenza e di arrivo dell’arco verificando quali siano i percorsi e la forma che l’arco deve assumere per rendere il concetto di flusso grafico, verificando quale siano i corretti valori delle variabili Lato_Partenza e Lato_Arrivo, che possono assumere i valori TL_Su, TL_Destra, TL_Giu, TL_Sinistra. Verificato questi, assegna agli oggetti di Linee le corrette coordinate e dimensioni, e immagini, rappresentando così l’arco. La procedura Evidenzia_Linker fa sì che gli oggetti grafici dell’arco vengano portati sopra tutte gli altri oggetti dello spazio di programmazione iconica, per evidenziare l’arco. Questo accade ogni volta che un’icona viene selezionata per rendere immediatamente disponibile la continuità del flusso da quell’icona. Le procedure Hide e Show, rispettivamente, nascondono e rendono visibile l’arco, iterando su tutti gli oggetti dell’istanza della classe. 118 4.4 Integrazione del parser XML Per salvare un progetto, i suoi files e le relative funzioni, sono state implementate tre classi derivate dalla classe TXMLDocument: TXML_Progetto, TXML_File, TXML_Funzione. 4.4.1 Classe TXML_Progetto La classe TXML_Progetto serve a salvare e recuperare i dati contenenti che compongono il progetto. E’ dichiarata come segue TXML_Progetto= class(TXMLDocument) private FFiles: array of String; public Nome: String; Percorso: String; constructor Create(AOwner: TComponent); overload; override; constructor Create(const AFileName: DOMString); reintroduce; overload; destructor Destroy; override; function Inserisci_File(File_: TXML_File): Boolean; function Elimina_File(Nome_File: String): Boolean; function Salva_Progetto(Figura: TForme): Boolean; function Carica_Progetto(Codice: String): Boolean; end; 119 L’array FFiles, di tipo string, memorizza tutti i files che compongono il progetto. Le variabili Nome e Percorso memorizzano rispettivamente il nome e il percorso della configurazione del progetto. I due costruttori Create, dichiarati override, ma anche overload ed reintroduce inizializzano l’array Files ed invocano i costruttori della classe genitrice. La classe può essere create richiamando uno dei due costruttori, a seconda se si vuole fornire in input un oggetto TComponent o un tipo DOMString ovvero una stringa. Il primo Create sovrascrive la procedura ereditata e, attraverso la keyword overload, la marca come unica procedura che può essere invocata nel caso in cui viene fornito in input un TComponent. Il secondo costruttore, attraverso la keyword reintroduce, dichiara implementabile la procedura in quanto nella classe genitrice il prototipo del costruttore è dichiarato come virtual, ovvero una procedura implementabile soltanto dalle classi derivate, e, attraverso la parola chiave overload, rende la procedura invocabile quando viene fornito a Create un dato di tipo Domstring, ovvero una stringa. Il distruttore Destroy libera la memoria utilizzata dall’array Files, ed invoca il distruttore ereditato. La funzione Inserisci_File riceve in input un dato TXML_File e memorizza tutti i suoi dati in formato XML e restituisce True se la memorizzazione avviene con successo, o False altrimenti. La funzione Elimina_File riceve in input il nome, di tipo stringa, interno di un oggetto TForme per eliminarlo da FForme e restituisce True se la cancellazione avviene con successo, o False altrimenti. 120 La funzione Salva_Progetto restituisce un valore booleano in accordo al successo del salvataggio. La procedura salva i parametri necessari per il suo successivo recupero. La funzione Carica_Progetto accetta in input una stringa dalla quale è possibile riprodurre l’intero progetto e restituisce il valore True se il progetto è stato caricato correttamente, o False altrimenti. 4.4.2 Classe TXML_File La classe TXML_File serve a salvare e recuperare i dati (funzioni, variabili, costanti, strutture e file include) contenenti che compongono il progetto. La classe è dichiarata come segue TXML_File= class(TXMLDocument) private FFunzioni: array of String; public Nome: String; Percorso: String; Include: array of String; Variabili: array of TDato_Matrice; Costanti: array of TDato_Matrice; Strutture: array of TStrutture; constructor Create(AOwner: TComponent); overload; override; constructor Create(const AFileName: DOMString); reintroduce; overload; destructor Destroy; override; function Inserisci_Funzione(Funzione: TXML_Funzione): Boolean; function Elimina_Funzione(Funzione: String): Boolean; 121 function Salva_File: Boolean; function Carica_File(Codice: String): Boolean; end; L’array FFunzioni, di tipo string, serve a memorizzare in ogni stringa le funzioni. Le variabili Nome e Percorso, di tipo string, memorizzano il nome e il percorso del file. La variabile Include è un array di tipo stringa. Questa serve a memorizzare quali sono le librerie di file dai quali il file, che si sta implementando, dipende. Le variavili Costanti e Variabili, due array di tipo TDato_Matrice, servono per memorizzare le variabili e le costanti globali. L’array Strutture, di tipo TStrutture, serve a memorizzare le strutture implementate nel file. Il tipo TStrutture è un array di TDato_Matrice. I costruttori e il distruttore di classe funziona in maniera analoga a TXML_Progetto, ma, in questo caso, vengono inizializzate e distrutte le variabili proprie della classe. La funzione Inserisci_Funzione riceve in input un dato TXML_Funzione, il quale viene memorizzato nella variabile FFunzioni, e restituisce un valore True se la memorizzazione avviene con successo, o False altrimenti. La funzione Elimina_Funzione riceve in input una stringa che identifica il nome della funzione da eliminare e restituisce un valore True se la memorizzazione avviene con successo, o False altrimenti. La funzione Salva_File restituisce un valore booleano: True se il file viene salvato o False altrimenti. 122 La funzione Carica_File, la quale riceve in input una stringa, restituisce un valore booleano in accordo all’esito del recupero dei dati memorizzati nella stringa Codice. 4.4.3 Classe TXML_Funzione La classe TXML_Funzione rappresenta la funzione implementata e la sua dichiarazione è come segue TXML_Funzione = class(TXMLDocument) private FForme: array of String; public constructor Create(AOwner: TComponent); overload; override; constructor Create(const AFileName: DOMString); reintroduce; overload; destructor Destroy; override; function Inserisci_Forma(Forma: TForme): Boolean; function Elimina_Forma(Forma: String): Boolean; function Salva_Funzione: Boolean; function Carica_Funzione(Codice: String): Boolean; end; L’array FForme di tipo string memorizza tutti i dati delle forme inserite. I costruttori Create e il distruttore di classe Destroy funziona similarmente alla precedente classe, ma inizializza soltanto la variabile FForme. 123 La funzione Inserisci_Forma riceve in input un dato TForme e memorizza tutti i suoi dati in formato XML all’interno di FForme e restituisce True se la memorizzazione avviene con successo, o False altrimenti. La funzione Elimina_Forma riceve in input il nome, di tipo stringa, interno di un oggetto TForme per eliminarlo da FForme e restituisce True se la cancellazione avviene con successo, o False altrimenti. La funzione Salva_Funzione restituisce un valore booleano: True se la funzione viene salvata o False altrimenti. La funzione Carica_Funzione, la quale riceve in input una stringa, restituisce un valore booleano in accordo all’esito del recupero dei dati memorizzati nella stringa Codice. 4.5 Implementazione sintetica dell’indicizzatore di librerie L’indicizzatore di librerie è un insieme di classi atte ad eseguire una serie di corrispondenze di testo tramite le funzioni di RegEx esternalizzate da una libreria di Perl. Le classi, utilizzate dall’applicazione, sono: TC_Metodo, TC_Sorgente. Ognuna di queste utilizza l’interfaccia IRegEx la quale incapsula le funzioni, tra le tante, della libreria di corrispondenza: IsMatch, Match, Matches, Split, Pattern. Per definire la regulare expression, reperire i prototipi e parametri accettati dalle funzioni, sono state inizializzate alcune stringhe: 124 Tipi = '(void|signed char|char|signed short|short|signed int|int|signed long|long|long long|float|double)'; VarNomeStr = '(\w+?)(((\s*)(\=(\s*)(.*))|));'; Usando queste stringhe si sono inizializzate le interface IRegEx nella seguente maniera MetodoRegEx := RegexCreate(Tipi + '([\w\s]*)'+'(\s+?)(\&|)(\w*)(\s*?)\((.*)\)', [rcoSingleLine, rcoUngreedy]); VarRegEx := RegexCreate(‘var(\s+?)' + Tipi + '(\s+?)' + '(\**)'+ VarNomeStr , [rcoSingleLine, rcoUngreedy]); Alla fine dell’analisi delle RegEx, tutti I dati vengono memorizzati in TC_Metodo, TC_Sorgente. 4.5.1 Classe TC_Sorgente TC_Sorgente deriva da un’altra classe TC_Classe la quale definisce alcuni metodi interni ed è una classe base, per TC_Sorgente, che contiene una variabile FMetodi di tipo TObjectList, ovvero una lista di oggetti. Per l’uso nell’applicativo, TC_Sorgente ha la seguente dichiarazione TC_Source = class(TC_Classe) protected function Prendi_Metodi(Index: Integer): TC_Metodo; override; 125 public property Metodi[Index: Integer]: TC_Metodo read Prendi_Metodi; constructor Create(const Testo_Sorgente: string); overload; destructor Destroy; override; end; la funzione Prendi_Metodi, dichiarata override e con visibilità protetta, sovrascrive la funzione della classe base e fornisce il Metodo indicato da Index quando si prova ad accedere alla proprietà Metodi. Il costruttore Create, dichiarata overload, riceve in input una costante di tipo stringa e analizza il testo alla ricerca di prototipi. Questi, quando riscontrati, verrano inseriti in FMetodi. Il distruttore Destroy, dichiarato override, libera la memoria dalle variabili interne. 4.5.2 Classe TC_Metodi La classe TC_Metodi è una classe che collezione i prototipi e la sua forma dichiarativa è la seguente TC_Method = class(TC_Entity) protected FMetodo_Nome: string; FMetodo_Prototipo: string; FMetodo_Corpo: string; FBracket_Inizio: Integer; FBracket_Fine : Integer; FParametri: array of TDato_Matrice 126 FTipo: string; function Prendi_Numero_Parametri: Integer; function Prendi_Parametri(Index: Integer): TDato_Matrice; public property Nome: string read FMetodo_Nome; property Prototipo: string read FMetodo_Prototipo; property Corpo: string read FMetodo_Corpo; property Bracket_Inizio: Integer read FBracket_Inizio; property Bracket_Fine: Integer read FBracket_Fine property Numero_Parametri: Integer read Prendi_Numero_Parametri; property Parametri[Index: Integer]: TDato_Matrice read Prendi_Parametri; property Tipo: string read FTipo; constructor Create(Parent: TC_Classe; const Occorrenza: string; TextPos: Integer); overload; override; destructor Destroy; override; end; Le variabili FMetodo_Nome, FMetodo_Prototipo e FMetodo_Corpo e i loro omonimi con visiblità pubblica, di tipo stringa, sono rispettivamente il nome, il prototipo e il corpo del prototipo trovato nella libreria analizzata. Le variabili FBracket_Inizio, e FBracket_Fine e i loro omonimi con visibilità pubblica, di tipo intero, corrispondono ai punti, rispettivamente, dove comincia e finisce il corpo della funzione. La variabile FTipo memorizza il tipo di dato in formato stringa e viene letto il suo valore mediante la proprietà Tipo; La funzione Prendi_Numero_Parametri, di tipo intero e con visibilità protetta poiché incapsulata, fornisce il quantitativo dei parametri richiesti dalla funzione e viene invocato implicitamente quando Numero_Parametri. 127 viene usato la proprietà La funzione Prendi_Parametri, la quale accetta un valore di tipo intero ed ha una visibilità protetta, restituisce un dato di tipo TDato_Matrice. Questa funzione fornisce il parametro memorizzato in FParametri e viene invocata implicitamente quando si usa la proprietà Parametri. Il costruttore Create, dichiarato override ed overload, riceve in input il proprietario della classe, di tipo TC_Classe, l’Occorrenza di tutto il prototipo rintracciato, di tipo stringa, e la posizione iniziale del testo in formato numerico intero. Il distruttore di classe Destroy libera la memoria di tutte le variabili usate dalla classe. 4.6 Implementazione del Text Editor Per l’implmentazione del componente Text Editor, che serve a visualizzare il codice in formato html, si è derivata una classe da TWebBrowser versione 6 e si sono incapsulate diverse variabili, proprietà ed eventi, ed una serie di funzioni e procedure secondo le specifiche delle librerie MSHTML della Microsoft. Si fornisce una breve descrizione della classe, mostrando alcune delle variabili, proprietà e funzioni aggiunte TMioWebBrowser = class(TWebBrowser) private FRead_Only: Boolean; function GetDocument1: IHTMLDocument; function GetDocument2: IHTMLDocument2; 128 function GetDocument3: IHTMLDocument3; function GetDocument4: IHTMLDocument4; function GetDocument5: IHTMLDocument5; function GetWindow2: IHTMLWindow2; function GetWindow3: IHTMLWindow3; function GetWindow4: IHTMLWindow4; function GetElementById1(Id: String): IHTMLElement; function GetElementById2(Id: String): IHTMLElement2; function GetElementById3(Id: String): IHTMLElement3; function GetElementById4(Id: String): IHTMLElement4; function GetElementByName1(Id: String): IHTMLElement; function GetElementByName2(Id: String): IHTMLElement2; function GetElementByName3(Id: String): IHTMLElement3; function GetElementByName4(Id: String): IHTMLElement4; function GetElementByTagName1(Id: String): IHTMLElement; function GetElementByTagName2(Id: String): IHTMLElement2; function GetElementByTagName3(Id: String): IHTMLElement3; function GetElementByTagName4(Id: String): IHTMLElement4; function GetAttribute(IdElement, AttributeName: String): String; function SetAttribute(IdElement, AttributeName, Value: String): Boolean; function RemoveAttribute(IdElement, AttributeName: String): Boolean; property Document1: IHTMLDocument read GetDocument1; property Document2: IHTMLDocument2 read GetDocument2; property Document3: IHTMLDocument3 read GetDocument3; property Document4: IHTMLDocument4 read GetDocument4; property Document5: IHTMLDocument5 read GetDocument5; property Windows2: IHTMLWindow2 read GetWindow2; property Windows3: IHTMLWindow3 read GetWindow3; property Windows4: IHTMLWindow4 read GetWindow4; procedure AboutBlank; procedure Pulisci; procedure InserisciHtml(Testo: String); function GetSelection: IHTMLSelectionObject; published property DesignMode: Boolean read FDesignMode write SetDesignmode default False; 129 property Read_Only: Boolean read FRead_Only write SetRead_Only default False; property OnDocumentDocumentClick : TEventi1 read FOnDocumentDocumentClick write FOnDocumentDoubleClick write SetOnDocumentDocumentClick ; property OnDocumentDoubleClick : TEventi1 read SetOnDocumentDoubleClick ; end; La variabile FRead_Only, di tipo booleano, rende capace il component di accettare o meno l’input dalla tastiera e viene modificato quando si cambiare il valore di Read_Only, il quale invoca la procedura SetRead_Only che modifica il comportamento del componente oltre a cambiare il valore di FRead_Only. Le funzioni GetDocumentX e GetWindowX, dove X è un numero da 1 a 5 per GetDocument e da 2 a 4 per GetWindow, restituiscono delle interfacce che forniscono diverse funzionalità, in accordo alla Microsoft, per poter agire sul componente e vengono invocate quando si cerca di ottenere un valore dalle proprietà DocumentX e WindowsX. Le funzioni GetElementByIdX, GetElementByNameX e GetElementByTagNameX, dove X è un numero, richiedono in input una stringa e forniscono una interfaccia di tipo IHTMLElement, IHTMLElement2, IHTMLElement3 o IHTMLElement4. Queste servono per cercare degli elementi all’interno del codice HTML attraverso o l’Id, o il Nome o il loto TagName. La funzione GetAttribute accetta in input due stringhe che identificano l’elemento e l’attributo di una interfaccia IHTMLElementX e restituisce il valore dell’attributo. 130 La funzione SetAttribute, oltre ad accettare gli stessi valori di GetAttribute, accetta anche un input di tipo stringa, Value, il quale serve a settare il valore desiderato. La funzione RemoveAttribute, riceve due stringhe le quali servono a identificare l’attributo da cancellare di un elemento html. La procedura AboutBlank permette di inizializzare il componente per permettere di poter interagire con esso. La procedura Pulisci permette di cancellare il contenuto html del componente e ,quindi, anche di ciò che visualizza. La procedura InserisciHtml riceve in input una stringa e la inserisce nel corpo html. La funzione GetSelection restituisce un’interfaccia che fornisce un elemento della selezione che si è resa nel componente.. Le proprietà OnDocumentDocumentClick e OnDocumentDoubleClick servono per implementare gli eventi che rispondono all’interazione con l’utente. 4.7 Implementazione delle caratteristiche del framework Per far si che il framework svolga le caratteristiche discusse, si sono implementate una serie di funzioni e procedure. L’applicativo, in fase di avvio, costruisce dinamicamente i bottoni che servono per la creazione degli oggeti. Questi bottoni, cliccati due volte o trascinati nell’area di lavoro, creano le icone associate. Durante la creazione delle icone mediante le funzioni Crea_XXX, dove XXX è il costrutto desiderato, vengono 131 assegnate alle proprietà delle icone una serie di procedure che ne determinano il controllo. Ad esempio, quando si seleziona clicca un’icona, questa richiama gli eventi ControlClick, ControlMouseDown, ControlMouseUp e ControlMouseUp che determinano alcuni comportamenti e qualora si dovesse eseguire un doppio click sull’icona, verrà aperta una finestra, associata al tipo di icona, la quale permette di interagire con essa e di assegnare il corretto codice del linguaggio C. Infatti, nella procedura di creazione delle icone, ad ognuna di esse viene assegnato una procedura DoubleClick_XXX, dove XXX è il costrutto associato. Inoltre, in fase di creazione viene anche associato all’icona un oggetto TPopUp, ovvero un menù a tendina che si apre quando l’utente clicca l’icona col tasto destro del mouse. Questo menù, simile in tutte le icone, eccezion fatta per alcune, fornisce una serie di possibilità all’utente per interagire con le icone, ad esempio può collegare nel flusso le icone o eliminarle. Completano il quadro le classiche funzioni di salvataggio del progetto e del file, nonché delle inizializzazioni di questi, oltre che la configurazione del progetto e dell’IDE e le funzioni di compilazione e di avvio del programma sviluppato. 132 Fig. 4.1 Esempio di un algoritmo creato con il framework con una icona selezionata 133 Conclusioni Nel corso della tesi si è voluto procedere all’analisi delle difficoltà e delle caratteristiche che i linguaggi iconici possiedono partendo dallo stato dell’arte nel campo di tali linguaggi. Si è, dunque, costruito un framework iconico che fornisca una chiara e semplice rappresentazione del linguaggio, utile all’implementazione di algoritmi e software che, mediante il proprio uso, costruisca un buon codice sorgente in linguaggio C. Inoltre, il framework si presta a essere utilizzato sia da principianti, che si accostano alla programmazione, sia da professionisti, in quanto, attraverso il linguaggio iconico, si evidenziano le logiche degli algoritmi che si sviluppano e i loro comportamenti. Infine, poiché il linguaggio iconico sfrutta una modellazione tipica dei Diagrammi a blocchi, il framework si rivela utilizzabile anche in ambito aziendale. Un ulteriore sviluppo è l’ampliamento del framework iconico affinché possa produrre il codice sorgente di altri linguaggi di programmazione quali: Pascal e Delphi, C++, Php, Java, JavaScript, Ruby, etc. 134 Bibliografia Abelson H., Sussman G. J., Sussman J., Structure and Interpretation of Computer Programs. 2nd ed., MIT Press, Cambridge, 1996. Ae T., Yamashita M., Cunha W. C., Matsumoto H., Visual user-interface of a programming system: MOPS-2, in Proceedings of IEEE Workshop on Visual Languages, Dallas, TX. IEEE CS Press, Silver Spring, 1986, pp. 44-53. Andries M., Engels G., Rekers J., Using graph grammars to represent visual programs, 1997. Antonietti A., Why does mental visualization facilitate problem solving?, in R. H. Logie, M. Denis, Mental Images in Human Cognition, Elsevier Science Publishers B. V., Amsterdam, 1991, pp. 211-227. Arnheim, R., Visual Thinking, University of California Press, Berkeley, 1969. Aufaure-Portier M. A., A high level interface language of GIS, in Journal of Visual Languages and Computing, 1995, pp. 167-182. 135 Badre A., Allen, J.. Graphic language representation and programming behavior, in S .Salvendy, M. J. Smith, Designing and Using HumanComputer Interfaces and Knowledge Based Systems, Elsevier Science Publishers, Amsterdam, 1989, pp. 59- 65. Bardohl R., Schultzke T., Taentzer G, Visual Language Parsing in GenGEd, in Proceedings of 2nd International Workshop on Graph Transformation and Visual Modeling Techniques GT-VMT ‘01, Creta, 2001. Barwise J., Etchemendy J., Hyperproof, Cambridge University Press, Cambridge, 1994 Barwise, J., Etchemendy J., Heterogeneous logic. In Diagrammatic Reasoning: Cognitive and Computational Perspectives. J. Glasgow, N. H. Narayanan, B. Chandrasekaran, (Eds.), AAAI Press, Menlo Park, CA and MIT Press, Cambridge, 1995, pp. 211-234. Beguelin A., Nutt G., Visual parallel programming and determinacy: a language specification, an analysis technique, and a programming tool, Journal of Parallel and Distributed Computing, 1994, pp. 235-250. 136 Bertin, J., Semiology of Graphics. Traduzione inglese di W. J. Berg, Università di Wisconsin Press, Madison, WI, 1983. Blackwell A. F., Metacognitive theories of visual programming: What do we think we are doing?, Proc. IEEE Symposium on Visual Languages, IEEE Computer Society Press, 1996, pp. 240-246. Bottoni P., Costabile M. F., Levialdi S., Mussio P., Formalizing visual languages, Proc. IEEE Symposium on Visual Languages, IEEE Computer Society Press, 1995, pp. 45-52. Bottoni P., Costabile M. F., Levialdi S., Mussio P., Specification of visual languages as means for interaction, Springer-Verlag New York, Inc. New York, New York, 1998. Bottoni P., Costabile M. F., Mussio P.,Specification and dialogue control of visual interaction through visual rewriting systems, ACM TOPLAS, 1999, pp. 1077-1136. Brooks F. P.,No silver bullet: Essence and accidents of software engineering, IEEE Computer, 1987, pp. 10-19. Brown M. H., Sedgewick R., Techniques for algorithm animation. IEEE Software, 1985, pp. 28-38. 137 Byrne M. D., Catrambone R., Stasko J. T., Do algorithm animations aid learning?, Tech. Rep. GIT-GVU-96-18, GVU Center, Georgia Institute of Technology, Atlanta, 1996. CACM, Special section on educational technology, Comunicazioni dell’ACM, 1996. Chang S. K., Costagliola G., Pacini G., Tortora G., Tucci M., Yu B., Yu J. S., A visual language system for user interfaces, IEEE Software, Vol. 12 , 1995, pp. 33-44. Chang S. K., Extending visual languages of multimedia, IEEE Multimedia, 1996, pp. 18-26. Chang S. K., Polese G., Orefice S., Tucci M., A methodology and interactive environment for iconic language design, in International Journal of Human Computer Studies, 1994, pp. 683-716. Chang S. K., Polese G., Thomas R., Das S., A visual language for authorization modeling, in Proceedings of 13esimo IEEE Symposium of Visual Languages, Capri, 1997pp. 110-118. Chang S. K., Tauber M. J., Yu B., Yu J. S., A visual language compiler, in IEEE Transactions on Software Engineering, 1989, pp. 506-525. 138 Chang S. K., Visual languages: A tutorial and survey, IEEE Software, 1987, pp. 29-39. Costagliola G., Delucia A., Orefice S., Polese G., A Classification Framework to Support the Design of Visual Languages, Journal of Visual Languages and Computing 2002, pp. 573-600. Costagliola G., Tortora G., Orefice S., De Lucia A., A parsing methodology for the implementation of visual systems, IEEE Transactions on Software Engineering, Vol. 23, 1997, pp. 777-799. Costagliola G., Tortora G., Orefice S., De Lucia A., Automatic generation of visual programming environments, IEEE Computer Vol. 28, 1995, pp. 56-66. Crimi C., Guercio A., Pacini G., Tortora G., Tucci M., Automating visual language generation, IEEE Transactions on Software Engineering Vol. 161, 1990, pp. 1122-1135. Cunniff N., Taylor R. P., Black J. B., Does programming language affect the type of conceptual bugs in begineers’ programs? A comparison of APL and Pascal, in Proceedings of SIGCHI ’86, Human Factors in Computing Systems, Boston, 1986, pp. 175-182. 139 Davis M.,Media stream: an iconic visual language for video annotation, in Proceedings of IEEE Symposium of Visual Languages. IEEE CS Press, Silver Spring, 1993, pp. 196-201. Dinesh T. B., Üsküdarli S., Specifying input and output of visual languages, Dipartimento di Software Technology, Amsterdam, 1997. Diskin Z., Dadish B., Piessens F., Johnson M.,Universal arrow foundations for visual modeling, in Theory and Application of Diagrams in M. Anderson, P. Cheng, V. Haarslev. Springer, Berlino, 2000, pp. 345360. Douglas S., Hundhausen C., McKeown D., Toward empirically-based software visualization languages, Proc. IEEE Symposium on Visual Languages, IEEE Computer Society Press, 1995, pp. 342-349. Douglass B.P., Real Time Uml, Addison Wesley, 2004. Ebert J., Winter A., Dahm P., Franzke A., Süttenbach R., Graph based modeling and implementation with EER/GRAK, in: Proceedings of ER’96,B.Thalheim, Springer, Berlino, 1996, pp. 163-178. Engelhardt Y., Bruin J., Janssen T., Scha, R., The visual grammar of information graphics, in N. H. Narayanan, J. Damski, Proc. AID’96 140 Workshop on Visual Representation, Reasoning and Interaction in Design, Key Center for Design Computing, Università di Sydney, 1996 Erwig M., Meyer B., Heterogeneous visual languages: Integrating visual and textual programming, Proc. IEEE Symposium on Visual Languages, IEEE Computer Society Press, 1995, pp. 318-325. Feder J., Plex languages, Information Science, Elsevier Science Inc. New York, 1971, pp. 225-241. Ferguson R. I., Hunter A., Hardy C., MetaBuilder: the diagrammer’s diagrammer, in Theory and Application of Diagrams, M. Anderson, P. Cheng,V. Haarslev, Springer, Berlino, 2000, pp. 407-421. Fowler M., Uml Distilled, Addison Wesley, 2003. Frank M. R., Foley J. D., A pure reasoning engine for programming by example, Tech. Rep. GIT-GVU-94-11, GVU Center, Georgia Institute of Technology, Atlanta, 1994. Freeman E., Gelernter D., Jagannathan S., In search of a simple visual vocabulary, Proc. IEEE Symposium on Visual Languages, IEEE Computer Society Press, 1995, pp. 302-309. 141 Fukunaga S., Kimura T. D., Pree W., Object-oriented development of a data flow visual language systems, in Proceedings of IEEE Symposium of Visual Languages. IEEE CS Press, Silver Spring,, 1993, pp. 134-141. Furnas G., New graphical reasoning models for understanding graphical interfaces, Proc.Human Factors in Computing Systems Conference (CHI’91), ACM Press, 1991, pp. 71-78. Furnas G., Reasoning with diagrams only, Proc. AAAI Spring Symposium on Reasoning with Diagrammatic Representations, AAAI Technical Report SS-92-02, AAAI Press, Menlo Park, 1992, pp. 118-123. Gero J. S., Yan M., Shape emergence by symbolic reasoning, Environment and Planning B: Planning and Design, 1994, pp. 191-218. Ghezzi C., Pezzeè M., Cabernet: an environment for the specification and verification of real-time systems, in DECUS Europe Symposium, Cannes, 1992. Ghezzi G., Mandrioli D., Morasca S., Pezzeè M., A unified high-level Petri net formalism for time-critical systems, IEEE Transactions on Software Engineering, Vol. 17, 1991. 142 Glasgow J., Narayanan N. H., Chandrasekaran B., Diagrammatic Reasoning: Cognitive and Computational Perspectives. AAAI Press, Menlo Park, CA and MIT Press, Cambridge, 1995. Glinert E. P., Nontextual programming environments, in S. K. Chang, Principles of Visual Programming Systems, Prentice-Hall, 1990, pp. 144230. Glinert E. P., Tanimoto L., Pict: an interactive graphical programming environment, IEEE Computer, Vol. 17, 1984, pp. 7-25. Glinert E., Towards second generation interactive graphical programming environments, in Proceedings of IEEE Workshop on Visual Language, IEEE CS Press, Silver Spring, 1986, pp. 61-70. Goel V., Sketches of Thought, MIT Press, Cambridge, 1995. Goldman N., Balzer R., The ISI visual design editor generator, In Proceedings of IEEE Symposium on Visual Languages, Tokyo, 1999, pp. 20-27. Golin E. J., Magliery T., A compiler generator for visual languages, in Proceedings of IEEE Workshop on Visual Languages, Bergen, 1993, pp. 314-321. 143 Gombrich E. H., Art and Illusion: A Study in the Psychology of Pictorial Representations. Phaidon, Londra, 1968. Gooday J. M., Cohn A. G., Visual language syntax and semantics: A spatial logic approach, Divisione di Articifial Intelligence, University of Leeds, Leeds, 1997. Goodman N., Languages of Art: An Approach to a Theory of Symbols, Hackett Publishing Company, Indianapolis, 1976. Graf M., A visual environment for the design of distributed systems, in Proceedings of IEEE Workshop on Visual Languages, Linkoping, Sweden. IEEE CS Press, Silver Spring, 1987, pp. 330-344. Green T. R. G., Cognitive dimensions of notations, in A. Sutcliffe e L. Macaulay,People and Computers V., Cambridge, Cambridge University Press, 1989, pp 443-460. Green T. R. G., Petre M., When visual programs are harder to read than textual programs, in G. C. van der Veer, M. J. Tauber, S. Bagnarola, M. Antavolits, Human-Computer Interaction: Tasks and Organization, Proc. 6th European Conference on Cognitive Ergonomics, 1992, pp.167-180. 144 Green T. R. G., Petre M., Bellamy R. K. E., Comprehensibility of visual and textual programs: A test of superlativism against the match-mismatch conjecture, in J. Koenemann- Belliveau, T. G. Moher, S. P. Robertson, Proc. Fourth Workshop on Empirical Studies of Programmers, Ablex Publishers, 1992. Green, T. R. G., Petre M., Usability analysis of visual programming environments: A cognitive dimensions framework. Journal of Visual Languages and Computing. 1996, pp. 131-174. Gross M., The fat pencil, the cocktail napkin, and the slide library, in A. Harfmann, M. Fraser, Proc. ACADIA 94, Association for Computer Aided Design in Architecture, 1994, pp.103-113. Gurr C. A., On the isomorphism (or otherwise) of representations, 1997. Haarslev V., A fully formalized theory for describing visual notations, International Workshop on the Theory of Visual Languages, Gubbio, 1996. Hammer E., Logic and visual information. In Studies in Logic, Language, Computation, CSLI Press, Stanford University, California, 1995. 145 Harel D., On visual formalisms. Communications of the ACM, 1988, pp. 514-530. Harel D., Statecharts: a visual formalism for complex system, Science of Computer Programming, Elseiver Science Publishers B.V. 1987, 231-274. Hegarty M., Just M. A., Constructing mental models of machines from text and diagrams, Journal of Memory and Language, 1993, pp. 717-742. Hegarty M., Mental animation: Inferring motion from static displays of mechanical systems, Journal of Experimental Psychology: Learning, Memory, Cognition, 1992, pp. 1084-1102. Hirakawa M., Tanaka M., Hichikawa T., An iconic programming system,HI-VISUAL, in IEEE Transactions on Software Engineering, 1990, pp. 178-184. Hix, D., Hartson H. R., Developing User Interfaces: Ensuring Usability Through Product & Process, John Wiley & Sons, Inc., New York, 1993. Hübscher R., Composing complex behavior from simple visual descriptions, Proc. IEEE Symposium on Visual Languages, IEEE Computer Society Press, 1996, pp. 88-94. 146 Hübscher R., Rewriting interaction, Proc. Human Factors in Computing Systems Conference (CHI’95), ACM Press, 1995. Huttenlocher J., Constructing spatial images: A strategy in reasoning, Psychological Review, 1968, pp. 550-560. Jacob R. J. K., A state transition diagram language for visual programming, IEEE Computer, Vol. 18, 1985, pp. 51-59. Johnson S. C., YACC: Yet another compiler compiler, Tech. Report 32, AT&T Bell Laboratories, Murray Hills, 1975. Joseph S. H., Pridmore T. P., Knowledge-directed interpretation of mechanical engineering drawings, IEEE Trans. on Pattern Analysis and Machine Intelligence, 1992, pp. 928-940. Kahn K. M., Saraswat V. A., Complete visualizations of concurrent programs and their executions, Proc. IEEE Symposium on Visual Languages, IEEE Computer Society Press, 1990, pp. 7-14. Karsai G., A configurable visual programming environment: a tool for domain specific programming, IEEE Computer, Vol 28, 1995, pp. 36-44. 147 Kimura T. D., Apte A., Sengupta S., Chan J. W., Form/formula: a visual programming paradigm for user-definable user interfaces, IEEE Computer, Vol. 28, 1995, pp. 27-35. Kimura T. D., HyperFlow: a visual programming language for pen computers, in Proceedings of IEEE Workshop on Visual Languages, Seattle,Washington. IEEE CS Press, Silver Spring, 1992, pp. 125-132. Kimura T. D., J Choi.W., Mack J. M., A visual language of keyboard-less programming, in Technical report WUCS-86-6, Department of Computer Science, Washington University, St. Louis, 1986. Koedinger K. R.,. Emergent properties and structural constraints: Advantages of diagrammatic representations for reasoning and learning, Proc. AAAI Spring Symposium on Reasoning with Diagrammatic Representations, AAAI Technical Report SS-92-02, AAAI Press, Menlo Park, 1992, pp. 154-169. Larkin J. H., Simon H. A., Why a diagram is (sometimes) worth ten thousand words, Cognitive Science, Carnegie-Mellon University, 1987, pp. 65-99. 148 Larkin J., Display based problem solving, in D. Klahr, K. Kotovsky, Complex Information Processing, Lawrence Erlbaum Publishers, Hillsdale, New York, 1989. Larman C., Applying UML and Patterns, Prentice Hall, 2005. Lohse G. I., Biolsi K., Walker N., Rueler H. H., A classification of visual representations. Comunicazioni dell’ACM, 1994, pp. 36-49. Lowe R. K., Constructing a mental representation from an abstract technical diagram, Learning and Instruction, Curtin University, Perth, 1993, pp. 157-179. Lowe R. K., Selectivity in diagrams: Reading beyond the lines, in Educational Psychology: An International Journal of Experimental Educational Psychology, 1994, pp. 467-491. Ludolph F., Chow Y.Y., Ingalls D., Wallace S., Doyle J., The fabrik programming environment , in Proceedings of IEEE Workshop on Visual Language, Pittsburgh, PA. IEEE CS Press, Silver Spring, 1988, pp. 222230. 149 Mahling D. E., Fisher D. L., The cognitive engineering of visual languages, Proc. IEEE Symposium on Visual Languages, IEEE Computer Society Press, 1990, pp. 22-28. Maimone M.W., Tygar J. D., Wing J. M., Micro Semantics fors ecurity, in Proceedings of IEEE Workshop on Visual Languages, Pittsburgh, PA. IEEE CS Press, Silver Spring, 1988, pp. 45-51. Marriott K., Meyer B., The CCMG visual language hierarchy, in Visual Language Theory, K.Marriot, B. Meyer, Springer, 1998. Marriott K., Meyer B., Towards a hierarchy of visual languages, Dipartimento di Computer Science, Monash University, Clayton, 1997. Marriott K., Meyer B., Wittenburg K., A survey of visual language specification and recognition, Springer-Verlag New York, Inc. New York, New York, 1998, pp. 5-85. Marriott K., Meyer B., Wittenburg K., A survey of visual language specification and recognition, in Visual Language Theory, K.Marriot, B. Meyer, Springer, 1998. Martin R., Uml for Java Programmers, Prentice Hall, 2003. McCorduck P., Aaron's Code, Freeman, San Francisco, 1991. 150 Menzies T., Frameworks for Assessing Visual Languages. Technical Report TR95-35, Department of Software Development, Monash University, 1995. Meyer B., Pictures depicting pictures: On the specification of visual languages by visual grammars Technical Report No. 139, Informatik Berichte, FernUniversitat, Hagen, 1993 , (In una versione più corta appare in Proc. 1992 IEEE Symposium on Visual Languages, IEEE Computer Society Press, pp. 41-47. Minas M., Concepts and realization of a diagram editor generator based on hypergraph transformation. Science of Computer Programming, to appear, Elsevier North-Holland, Amsterdam, 2002. Moriconi M., Hare D. F., Visualizing program design through PegaSys, IEEE Computer, Vol. 18, 1985, pp. 72-85. Musen M. A., Fagen L. M., Shortliffe E. H., Graphical specification of procedural knowledge for an expert system, in Proceedings of IEEE Workshop on Visual Languages, Dallas, 1986, pp. 167-178. 151 Myers B., Visual programming, programming by example and program visualization: A taxonomy. Proc. Human Factors in Computing Systems Conference (CHI’86), ACM Press, 1986, pp. 59-66. Najork M., Golin E. J., Enhancing show-and-tell with a polymorphic type system and higher order functions, in Proceedings of IEEE Workshop on Visual Languages, Skokie, 1990. Narayanan H. N., Hübscher R., Visual language theory: towards a Human-Computer interaction perspective, Technical Report CSE97-05, 1997. Narayanan N. H., Hegarty M., On designing comprehensible interactive hypermedia manuals. International Journal of Human-Computer Studies, Associate Editor, 1998, pp. 267-301. Narayanan N. H., Proc. AAAI Spring Symposium on Reasoning with Diagrammatic Representations. AAAI Technical Report SS-92-02, AAAI Press, Menlo Park, 1992. Narayanan N. H., Suwa M., Motoda H., A study of diagrammatic reasoning from verbal and gestural protocols, Proc. 16th Annual 152 Conference of the Cognitive Science Society, Lawrence Erlbaum Associates, 1994, pp. 652-657. Narayanan N. H., Suwa M., Motoda H., How things appear to work: Predicting behaviors from device diagrams.,Proc. 12th National Conference on Artificial Intelligence, AAAI Press, 1994, pp. 1161-1167. Narayanan N. H., Suwa M., Motoda, H., Diagram-based problem solving: The case of an impossible problem, Proc. 17th Annual Conference of the Cognitive Science Society, Lawrence Erlbaum Associates, 1995, pp. 206211. Narayanan N. H., Suwa, M., Motoda, H., Behavior hypothesis from schematic diagrams, in Diagrammatic Reasoning: Cognitive and Computational Perspectives, J. Glasgow, N. H. Narayanan, B. Chandrasekaran, (Eds.) AAAI Press and MIT Press, 1995, pp. 501 -534. Nassi I., Shneiderman B., Flowchart techniques for structured programming, in ACM SIGPLAN Notice, 1973, pp. 12-26. Newell A., Simon H. A., Human Problem Solving, Prentice-Hall, Englewood Cliffs, 1972. 153 Newman W. M., Lamming M. G., Interactive System Design. AddisonWesley, Wokingham, 1995. Nickerson J. V., Visual programming: Limits of graphic representation, Proc. IEEE Symposium on Visual Languages, IEEE Computer Society Press, 1994, pp. 178-179. Norman D. A., Cognitive engineering, in D. A. Norman, S. W. Draper, User Centered System Design, Lawrence Erlbaum Associates, Hillsdale, 1986, pp. 31-65. Norman D. A., The Psychology of Everyday Things, Basic Books, New York, 1988. Novak G. S., Bulko W. C., Diagrams and text as computer input, Journal of Visual Languages and Computing, 1993, pp. 161-175. Petre M., Blackwell A. F., Green T. R. G., Cognitive questions in software visualization, in J. Stasko, J. Domingue, B. Price, M. Brown, Software Visualization: Programming as a Multi-Media Experience, MIT Press. Petre M., Why looking isn't always seeing: Readership skills and graphical programming. Communications of the ACM, 1995, pp. 33-44. 154 Pietrzykowsky T., Matwin S., Muldner T., The programming language PROGRAPH: yet another application of graphics, in Proceedings of Graphics Interface ‘83, Edomonton, 1983, pp. 143-145. Price B. A., Baecker R. M., Small I. S., A principled taxonomy of software visualization. Journal of Visual Languages and Computing, 1993, pp. 211-266. Puigsegur J., Agusti J., Robertson, D., A visual programming language, Proc. IEEE Symposium on Visual Languages, IEEE Computer Society Press, 1996, pp. 214-215. Raymond D. R., Characterizing visual languages, Proc. IEEE Symposium on Visual Languages, IEEE Computer Society Press, 1991, pp. 176-182. Repenning A., Bending the rules: Steps toward semantically enriched graphical rewrite rules, Proc. IEEE Symposium on Visual Languages, IEEE Computer Society Press, 1995, pp. 226- 233. Repenning A., Sumner T., Agentsheets: A medium for creating domainoriented visual languages, IEEE Computer, 1995, pp. 17-25. Resnick M., Beyond the centralized mindset, Journal of the Learning Sciences, 1996, pp. 1-22. 155 Robertson G. G., Card S. K., Mackinlay J. D., Information visualization using 3D interactive animation, Communications of the ACM, 1993, pp. 57-71. Rohr G., Using visual concepts, in Visual Languages , S. K. Chang, T. Ichikawa, P. Ligomenides, Plenum, NewYork., 1986. Ross D.T., Schoman K. E. Jr, Structured analysis for requirement definition, IEEE Transactions on Software Engineering, 1977, pp. 6-15. Rumbaugh J., Jacobson I., Booch G., The Unified Modeling Language Reference Manual, Addison-Wesley Object Technology Series, AddisonWesley, 1998. Rumbaugh J., Jacobson I., Booch G., The Unified Modelling Language Reference manual, Addison Wesley, 2005. Saint-Martin F., Semiotics of Visual Language. Indiana University Press, Bloomington, 1990. Schwartz D. L., Black J. B., Analog imagery in mental model reasoning: Depictive models, Cognitive Psychology, 1996, pp. 154-219. Selker T., Koved L., Elements of visual language, Proc. IEEE Symposium on Visual Languages, IEEE Computer Society Press, 1988, pp. 38-44. 156 Shepard R. N., Cooper L. A., Mental Images and Their Transformations, MIT Press, Cambridge, 1986. Shin S.J., The Logical Status of Diagrams. Cambridge University Press, Cambridge, 1994. Shu N. C., Visual programming languages: A perspective and a dimensional analysis, in S. K. Chang, T. Ichikawa, P. A. Ligomenides, Visual Languages, Plenum Publishing Corporation, New York, 1986, pp. 11-34. Sinha A., Vessey I., Cognitive fit in recursion and iteration: An empirical study, IEEE Trans. on Software Engineering, 1992, pp. 386-379. Smith D. C., Cypher A., Spohrer J., Kidsim: Programming agents without a programming language, Communications of the ACM, 1994, pp. 54-68. Smith D. N., Visual programming in the interface construction, in Proceedings of IEEE Workshop on Visual Languages, Pittsburgh, PA. IEEE CS Press, Silver Spring, 1988, pp.109-120. Smith R. B., The alternate reality kit: An animated environment for creating interactive simulations, Proc. IEEE Symposium on Visual Languages, IEEE Computer Society Press, 1986, pp. 99-106. 157 Steinman S., Carver K.,. Visual programming with Prograph CPX, Manning Publications/Prentice Hall, Englewood Cliffs, 1995. Stenning K., Cox R., Oberlander J., Contrasting the cognitive effects of graphical and sentential logic teaching: Reasoning, representation and individual differences, Language and Cognitive Processes, 1995, pp. 333354. Stenning K., Oberlander J., A cognitive theory of graphical and linguistic reasoning: Logic and implementation, Cognitive Science, 1995, pp. 97140. Tessler S., Iwasaki Y., Law K., Qualitative structural analysis using diagrammatic reasoning, in Diagrammatic Reasoning: Cognitive and Computational Perspectives, J . Glasgow, N. H. Narayanan, B. Chandrasekaran, (Eds.), AAAI Press and MIT Press, 1995, pp. 711-730. Tufte E. R., The Visual Display of Quantitative Information, Graphics Press, Cheshire, 1983. Tufte E. R., Visual Explanations, Graphics Press, Cheshire, 1997. Tufte E. R., Envisioning Information, Graphics Press, Cheshire, 1990. 158 Tversky B., Cognitive origins of graphic productions, in F. T. Marchese, Understanding Images: Finding Meaning in Digital Imagery, SpringerVerlag, New York, 1995, pp. 29-53. Wang D., Lee J. R., Zeevat H., Reasoning with diagrammatic representations, in Diagrammatic Reasoning: Cognitive and Computational Perspectives, J. Glasgow, N. H. Narayanan, B. Chandrasekaran, (Eds.), AAAI Press and MIT Press, 1995, pp. 339-396. Wang D., Zeevat H., A syntax directed approach to picture semantics, CWI, Amsterdam, 1997. Wellner P. D., StateMaster: a UIMS based on statecharts for prototyping and target implementation, in Proceedings of SIGCHI ’89, Human Factors in Computing Systems, Austin, 1989, pp. 177-182. Wittenburg K., Weitzman, L., Relational grammars: Theory and practice in a visual language interface for process modeling, 1997. Zhang D., Zhang K., VisPro: a visual language generation toolset, in Proceedings of IEEE Symposium on Visual Languages, Halifax, 1999, pp. 195-202. 159