Per discutere la parte HARDWARE il topic è questo: http://www.nonsoloamiga.com/index.php?topic=3115Ciao ragazzacci,
butto giù un po' di spunti e idee per la calcolatrice che sto sviluppando nel tempo libero. Discussione aperta a suggerimenti di ogni tipo!
Per facilitare l'implementazione su sistemi embedded ho iniziato lo sviluppo in due moduli principali: MathLang e un client testuale.
MathLang è una libreria statica in C++ puro (variante C++11), mentre Text Client è solo un aggancio lato console per inviare comandi (sotto forma di script) e ricevere risposte (come stringhe).
Una volta che l'engine sarà a buon punto sarà possibile creare un client diverso, magari con una bella grafica, adatto al dispositivo di destinazione.
MathLang è composto a sua volta da due parti principali: ScriptEngine per parsare ed eseguire gli script e MathEngine per l'esecuzione delle operazioni matematiche elementari.
A partire da uno script viene generato un albero ordinato (a parità di parent, i figli sono ordinati da sinistra a destra), dove ogni nodo è uno Statement e ogni statement a sua volta può essere un albero o una foglia.
BlockStatement, CallFunctionStatement, ReturnStatement, LoopStatement e ConditionalStatement sono alberi, mentre DefinitionStatement, AssignmentStatement sono foglie.
ScriptEntity rappresenta le entità più semplici (StringEntity, FunctionEntity, RealEntity, MatrixEntity, BooleanEntity, ListEntity, ecc...) e viene usata come classe base per gli argomenti e i tipi di ritorno delle Function.
Lo
Script minimale è costituito da uno Statement, uno ScriptEnvironment, una lista di ScriptEntity (gli argomenti) e almeno un ReturnStatement. Lo script quindi rappresenta il concetto matematico di funzione.
Statement è la classe base che rappresenta i comandi elementari.
ScriptEnvironment è una mappa key-value di stringhe vs ScriptEntity. Contiene le variabili locali e gli argomenti della chiamata a funzione. Non esistono variabili globali.
DefinitionStatement rappresenta la definizione di un simbolo all'interno dello ScriptEnvironment () e la sua inizializzazione
AssignmentStatement rappresenta l'assegnazione di una nuova Entity dello stesso tipo o di un tipo compatibile rispetto a quello con cui è stata definita nell'Environment (se definisco una stringa e poi assegno un intero si incazza).
BlockStatement è un array di Statement.
CallFunctionStatement prende 2 parametri: FunctionEntity da chiamare e ListEntity per gli argomenti (possono essere a loro volta delle FunctionEntity). La FunctionEntity fa riferimento ad un nuovo script
ReturnStatement prende 1 parametro: ScriptEntity (classe base) da restituire al chiamante dello script
LoopStatement prende come parametri 3 oggetti: ScriptEntity contatore, ListEntity con i possibili valori da assegnare al contatore, Statement come corpo del loop
ConditionalStatement prende 3 parametri: BooleanEntity che è la condizione, Statement per il ramo IF e un altro Statement per il ramo ELSE
I vari tipi di ScriptEntity sono:
StringEntity: incapsula il concetto di stringa e le operazioni su di essa
FunctionEntity: incapsula il concetto di funzione, fa riferimento ad un nuovo Script, che possiede quindi un proprio Environment privato.
RealEntity: incapsula i numeri reali (double precision)
IntegerEntity: incapsula i numeri interi a precisione arbitraria (forse userò una lib già pronta per questi algoritmi)
BooleanEntity: incapsula il concetto di boolean
ListEntity: incapsula il concetto di lista eterogenea ordinata (la posizione è preservata)
SetEntity: incapsula il concetto di insieme eterogeneo non ordinato
MatrixEntity: incapsula il concetto di vettore multidimensionale omogeneo (tutte le Entity devono essere dello stesso tipo)
Ora.... alcune delle cose di cui sopra sono già state implementate, altre sono solo nella mia testa. Non ho ancora pensato ad una sintassi precisa per gli script, per cui accetto suggerimenti. Pensavo di basarmi su alcuni spunti presi da TI Basic e Python.
MathEngine espone al pubblico sia un'interfaccia di scripting executeScript(std::string text), sia un'inferfaccia a oggetti executeScript( Script* script ), per cui la prima parte dello sviluppo avverrà tramite la costruzione manuale dell'albero dello script e successivamente, quando avrò definito con precisione la grammatica, metterò mano ad un parser per gli script testuali.
Questo mi consente comunque la possibilità di avere in futuro una GUI furba che consenta di editare gli elementi in modo visuale, senza passare dallo script testuale, semplicemente manipolando gli oggetti dello Script.
Il progetto NON vuole essere un clone di Matlab o Mathematica (sarebbe pura e semplice follia), ma un esperimento ludico molto più modesto incentrato sul calcolo numerico. Mi piacerebbe in futuro aggiungere anche capacità di calcolo simbolico, ma è un argomento molto complesso e non credo di poterci arrivare con le mie capacità
Bon... vi aggiornerò con i progressi!
Fatevi sotto con le vostre idee, commenti e spunti