CREATIVITA' > Altri Hobby & Passioni

Idee e spunti per una calcolatrice - Parte Software

(1/8) > >>

TheKaneB:
Per discutere la parte HARDWARE il topic è questo: http://www.nonsoloamiga.com/index.php?topic=3115


Ciao 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à :D

Bon... vi aggiornerò con i progressi!
Fatevi sotto con le vostre idee, commenti e spunti :)

TheKaneB:
I numeri di riga non hanno senso di esistere nel 2015 :D
Sembra simile al Pascal perchè mi piace la tipizzazione forte (e mi piace il Pascal) :)

Però, ripeto, al momento non ho ancora pensato alla sintassi, solo alla semantica dei tipi.

TheKaneB:
Appena metterò mano sulla grammatica e relativo parser vedrò di studiare bene la faccenda. Al momento voglio focalizzarmi sulla semantica e l'engine di calcolo :)

TheKaneB:
Se alla Human interface hai un Line Editor non sei ancora nel 2015, ritenta tra qualche secolo ;D ;D ;D

Uhm... non mi piace il fatto che Little legge il testo man mano che lo interpreta (https://code.google.com/p/little-interpreter/source/browse/little.cpp).
Un po' troppo naive come approccio. Preferisco avere un AST di mezzo su cui poter fare delle operazioni prima della reale esecuzione, altrimenti ti leghi troppo alla sintassi ( e ripeto, che voglio offrire l'accesso all'albero rappresentato dalla classe Script, in modo da consentire al client un'interazione più libera possibile, anche tramite strumenti grafici e non solo testo).

TheKaneB:
infatti, quella roba puzzava di università lontano kilometri :D
Io ho sviluppato una forte repulsione per i metodi di scrittura del codice che insegnano all'Uni. Roba veramente distaccata dal mondo reale del software engineering.
Scrivere un interprete in quel modo ti porta via molto più tempo che usando un AST e la mantenibilità futura è praticamente nulla.

Un bel sistema a oggetti, con un AST ben definito si scrive molto facilmente e i singoli pezzi sono debuggabili come entità chiuse a se stanti. Puoi applicare facilmente centinaia di Unit Test e implementare roba futura in modo additivo senza spaccare le robe precedenti. Se invece ti appoggi pesantemente alla struttura sintattica, ogni modifica o aggiunta diventa "write only", auguri a debuggare ed espandere :D

Sarà una mia deformazione professionale, ma anche quando scrivo roba per hobby cerco di usare le tecniche più pulite che conosco, perchè so che mi aiuteranno a produrre di più in meno tempo e con meno sbattimenti :)

Navigazione

[0] Indice dei post

[#] Pagina successiva

Vai alla versione completa